그래서 기본적으로 인스턴스화 된 중첩 된 개체를 유지하면서 비어있는 Json 노드를 줄이기 위해 작동하는 추한 솔루션을 만들었습니다. 이 솔루션에는 재귀를 사용하여 Json을 줄이기 위해 일부 유형 매핑과 함께 DefaultContractResolver 구현을 사용하는 것이 포함됩니다.여기
가 계약 확인자입니다 : 내가 지정한 어떤 정체성 작동, Type 클래스에 대한 확장 방법
public class ShouldSerializeContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (property.GetType().GetTypeName() == "object")
{
property.ShouldSerialize =
instance =>
{
var value = instance.GetType().GetProperty(property.UnderlyingName).GetValue(instance, null);
if (value == null)
{
return false;
}
if (value.GetType().GetTypeName() == "object")
{
if (NodeHasValue(value))
{
return true;
}
}
else
{
if (value.GetType().GetTypeName() == "collection")
{
ICollection enumerable = (ICollection)value;
if (enumerable.Count != 0)
{
return true;
}
else
{
return false;
}
}
return true;
}
return false;
};
}
return property;
}
public bool NodeHasValue(object obj)
{
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
var value = property.GetValue(obj, null);
if (value == null)
{
return false;
}
if (value.GetType().GetTypeName() == "object")
{
return NodeHasValue(value);
}
if (value.GetType().GetTypeName() == "collection")
{
ICollection enumerable = (ICollection)value;
if (enumerable.Count != 0)
{
return true;
}
}
if (value.GetType().GetTypeName() == "array")
{
IList enumerable = (IList)value;
if (enumerable.Count != 0)
{
return true;
}
}
if (value.GetType().GetTypeName() != "object"
&& value.GetType().GetTypeName() != "collection"
&& value.GetType().GetTypeName() != "array")
{
if (value != null)
{
var attribute = property.GetCustomAttribute(typeof(DefaultValueAttribute)) as DefaultValueAttribute;
if (attribute.Value.ToString() != value.ToString())
{
return true;
}
}
}
}
return false;
}
}
메소드 GetTypeName()되어 컬렉션, 객체, 배열 대 기본 유형입니다. 6, "objectB": { "propertyA - : GetTypeName에 대한
확장 방법 클래스()`{"propertyA "
public static string GetTypeName(this Type type)
{
if (type.IsArray)
{
return "array";
}
if (type.GetTypeInfo().IsGenericType)
{
if (type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return GetTypeName(Nullable.GetUnderlyingType(type)) + '?';
}
var genericTypeDefName = type.Name.Substring(0, type.Name.IndexOf('`'));
var genericTypeArguments = string.Join(", ", type.GenericTypeArguments.Select(GetTypeName));
if (type.GetTypeInfo().GetInterfaces().Any(ti => ti.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
return "collection";
}
return $"{genericTypeDefName}<{genericTypeArguments}>";
}
string typeName;
if (_primitiveTypeNames.TryGetValue(type, out typeName))
{
return typeName;
}
// enum's come up as a ValueType so we check IsEnum first.
if (type.GetTypeInfo().IsEnum)
{
return "enum";
}
if (type.GetTypeInfo().IsValueType)
{
return "struct";
}
return "object";
}
private static readonly Dictionary<Type, string> _primitiveTypeNames = new Dictionary<Type, string>
{
{ typeof(bool), "bool" },
{ typeof(byte), "byte" },
{ typeof(byte[]), "byte[]" },
{ typeof(sbyte), "sbyte" },
{ typeof(short), "short" },
{ typeof(ushort), "ushort" },
{ typeof(int), "int" },
{ typeof(uint), "uint" },
{ typeof(long), "long" },
{ typeof(ulong), "ulong" },
{ typeof(char), "char" },
{ typeof(float), "float" },
{ typeof(double), "double" },
{ typeof(string), "string" },
{ typeof(decimal), "decimal" }
};
}
당신은 당신이이보고 싶지 않아인가 ": 2}}', 왜냐하면'ObjectB'도'ObjectA'의'PropertyA'와 같이 null이 아닌 프로퍼티를 가지고 있기 때문입니다 ... – gkb
DefaultValueHandling.Ignore는 ObjectB의 PropertyA를 결과에서 제외해야합니다. – Jamie
objectA의 PropertyA도 무시하면 안됩니까? – gkb