我有几个生成的.NET类有三个级别,我想以特殊格式序列化它们。所以,我开始使用Newtonsoft.Json编写一个自定义的Json Serializer。
我认为很难完全解释,所以我在此处发布了代码以及目标:https://dotnetfiddle.net/CDGcMW
基本上,有一个包含对象的初始数组,并且会有该对象的属性。困难的部分是这些属性未知,因此我尝试创建自定义序列化器。
任何帮助确定我如何在这里制作Json https://dotnetfiddle.net/CDGcMW成为"目标"我们非常感谢JSON的评论。
编辑:将dotnetfiddle更新为更小的示例。原文在这里:https://dotnetfiddle.net/dprfDu
答案 0 :(得分:3)
你的目标" JSON处理起来很棘手,因为SubDataMappers
列表的处理方式不同,具体取决于子项是否具有非空DataMapperProperty
或非SubDataMappers
列表。在前一种情况下,您希望将其呈现为每个子DataMapper
包含一个属性的对象;在后者中,作为一个对象数组,每个对象包含一个DataMapper
。此外,我发现您使用Name
的{{1}}属性作为JSON中的键,而不是知名属性的值。鉴于这两个限制,我认为最好的攻击计划是使DataMapper
在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
,这在每个级别都是唯一的。Name
永远不会同时包含非空DataMapper
和非空DataMapperProperty
列表。SubDataMappers
将始终具有非空DataMapperProperty
。DataType
永远不会有DataMapper
Name
。如果最后四个假设不成立,则此JSON格式不适用于您尝试执行的操作,您需要重新考虑。
要使用转换器,您需要将其添加到序列化设置中,如下所示。在序列化和反序列化时使用这些设置。从data-type
类中删除[JsonConverter]
属性。
DataMapper
这是一个往返演示:https://dotnetfiddle.net/8KycXB
答案 1 :(得分:0)
您可以使用ExpandoObject替换所有类型的类,从而使用JSON.NET实现深层嵌套序列化。这个对我有用。让我知道它是否适合您或需要任何样本来向您展示。
更新:
这是工作样本
https://dotnetfiddle.net/jtebDs
希望这是你想看到的输出。如果您有任何问题,请告诉我。