당신의 "목표"JSON은 SubDataMappers
목록의 치료는 아이들이 null이 아닌 DataMapperProperty
또는 SubDataMappers
의 비어 있지 않은 목록을 가지고 있는지 여부에 따라 다르기 때문에 처리하기 까다 롭습니다. 전자의 경우 자식 당 하나의 속성을 포함하는 객체로 렌더링하려고합니다. DataMapper
; 후자는 각각 DataMapper
을 포함하는 객체의 배열입니다. 또한 잘 알려진 속성의 값이 아닌 DataMapper
의 Name
속성을 JSON의 키로 사용하고 있습니다. 이 두 가지 제약 조건을 감안할 때 최선의 공격 계획은 목록 (DataMappers
)에서 작동하는 JsonConverter
을 단일 인스턴스로 만드는 것이라고 생각합니다. 그렇지 않으면 컨버터 코드가 꽤 엉망이 될 것입니다.
public class DataMapperListConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(List<DataMapper>);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
List<DataMapper> list = (List<DataMapper>)value;
if (list.Any(dm => dm.DataMapperProperty != null))
{
JObject obj = new JObject(list.Select(dm =>
{
JToken val;
if (dm.DataMapperProperty != null)
val = JToken.FromObject(dm.DataMapperProperty, serializer);
else
val = JToken.FromObject(dm.SubDataMappers, serializer);
return new JProperty(dm.Name, val);
}));
obj.WriteTo(writer);
}
else
{
serializer.Serialize(writer,
list.Select(dm => new Dictionary<string, List<DataMapper>>
{
{ dm.Name, dm.SubDataMappers }
}));
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return token.Children<JProperty>()
.Select(jp =>
{
DataMapper mapper = new DataMapper { Name = jp.Name };
JToken val = jp.Value;
if (val["data-type"] != null)
mapper.DataMapperProperty = jp.Value.ToObject<DataMapperProperty>(serializer);
else
mapper.SubDataMappers = jp.Value.ToObject<List<DataMapper>>(serializer);
return mapper;
})
.ToList();
}
else if (token.Type == JTokenType.Array)
{
return token.Children<JObject>()
.SelectMany(jo => jo.Properties())
.Select(jp => new DataMapper
{
Name = jp.Name,
SubDataMappers = jp.Value.ToObject<List<DataMapper>>(serializer)
})
.ToList();
}
else
{
throw new JsonException("Unexpected token type: " + token.Type.ToString());
}
}
}
가정 : 그 허용하는 경우, 다음 컨버터는 당신이 원하는 무엇을 제공해야
- 당신은 결코 그 자체로 하나의
DataMapper
를 직렬화되지 않습니다; 그것은 항상 목록에 포함됩니다.
DataMappers
은 임의의 깊이로 중첩 될 수 있습니다.
DataMapper
은 항상 각 레벨에서 고유 한 Name
이 아닌 null이됩니다.
DataMapper
은 0이 아닌 DataMapperProperty
과 비어 있지 않은 목록 인 SubDataMappers
을 가질 수 없습니다.
DataMapperProperty
은 항상 null이 아닙니다 DataType
입니다.
DataMapper
은 Name
이 data-type
이되지 않습니다.
마지막 4 가지 가정이 사실이 아니라면,이 JSON 형식은 수행하려는 작업에 적합하지 않으므로 다시 생각해 봐야합니다.
변환기를 사용하려면 다음과 같이 변환기를 serializer 설정에 추가해야합니다. serialize 및 deserialize 할 때 설정을 사용하십시오. DataMapper
클래스에서 [JsonConverter]
특성을 제거하십시오.https://dotnetfiddle.net/8KycXB
정말 잘 모르겠습니다. 객체 그래프에 깊게 중첩 될 때 유형의 속성을 제외 시키려고하지만 그래프 상단에있는 경우는 제외합니다. 그렇다면 아마도 [Json.NET은 깊이와 속성에 의해 직렬화됩니다] (https://stackoverflow.com/q/36159424/3744182) 도움이 될 것입니다. – dbc
그 링크가 도움이되지 않는다면 가능한 한 적은 외부 필드와 속성으로 현재 출력과 필요한 출력을 보여주는 [mcve]로 피들을 단순화 할 수있는 방법이 있습니까? – dbc
감사합니다. 예제를 더 짧게 업데이트했으며 IContractResolver를 살펴 보겠습니다. – ajtatum