我有几个生成的.NET类深入了三个级别,我想以一种特殊的格式对其进行序列化。因此,我开始使用Newtonsoft.Json编写自定义的Json序列化器。
我相信很难完全解释,因此我在此处将代码和目标一起发布了:https : //dotnetfiddle.net/CDGcMW
本质上,存在一个包含对象的初始数组,并且该对象具有属性。困难的部分是这些属性未知,这就是为什么我尝试创建自定义序列化程序的原因。
在确定如何使这里https://dotnetfiddle.net/CDGcMW产生的Json成为注释中的“目标” JSON方面的任何帮助将不胜感激。
编辑:将dotnetfiddle更新为一个较小的示例。原始文件在这里:https : //dotnetfiddle.net/dprfDu
您的“目标” JSON很难处理,因为SubDataMappers
根据子代具有的非DataMapperProperty
空列表还是非空列表,对列表的处理方式有所不同SubDataMappers
。在前一种情况下,您希望将其呈现为每个孩子包含一个属性的对象DataMapper
;在后者中,作为对象数组,DataMapper
每个对象包含一个对象。另外,我看到您使用的Name
属性DataMapper
作为JSON中的键,而不是众所周知的属性的值。由于这两个限制,我想攻击的最佳方案是让JsonConverter
运营一个在名单中DataMappers
而不是单个实例。否则,转换器代码将变得非常混乱。如果可以接受,那么以下转换器应为您提供所需的东西:
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
将始终具有非null Name
,在每个级别上都是唯一的。DataMapper
绝不会同时包含的非DataMapperProperty
空列表和非空列表SubDataMappers
。DataMapperProperty
将始终具有非null DataType
。DataMapper
将永远不会有一个Name
的data-type
。如果最后四个假设不成立,则此JSON格式将无法满足您的尝试,因此您需要重新考虑。
要使用转换器,您需要将其添加到序列化器设置中,如下所示。序列化和反序列化时都使用设置。[JsonConverter]
从DataMapper
类中删除该属性。
var settings = new JsonSerializerSettings()
{
Converters = new List<JsonConverter> { new DataMapperListConverter() },
Formatting = Formatting.Indented
};
这是一个往返演示:https : //dotnetfiddle.net/8KycXB
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句