自定义Json序列化器,用于深层嵌套对象

速效

我有几个生成的.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 可以嵌套到任意深度。
  • ADataMapper将始终具有非null Name,在每个级别上都是唯一的。
  • ADataMapper绝不会同时包含的非DataMapperProperty空列表和非空列表SubDataMappers
  • ADataMapperProperty将始终具有非null DataType
  • 一个DataMapper将永远不会有一个Namedata-type

如果最后四个假设不成立,则此JSON格式将无法满足您的尝试,因此您需要重新考虑。

要使用转换器,您需要将其添加到序列化器设置中,如下所示。序列化和反序列化时都使用设置。[JsonConverter]DataMapper类中删除该属性

var settings = new JsonSerializerSettings()
{
    Converters = new List<JsonConverter> { new DataMapperListConverter() },
    Formatting = Formatting.Indented
};

这是一个往返演示:https : //dotnetfiddle.net/8KycXB

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Jackson自定义反序列化器,用于多态对象和String文字作为默认值

用于Optional <?>的Jackson自定义序列化程序

自定义BigInteger JSON序列化器

JSon-嵌套地图的自定义键序列化

使用杰克逊的对象数组的自定义序列化器

自定义JSON编码器引发“对象无法JSON序列化”错误

为地图和/或嵌套对象自定义Spring @RequestParam反序列化

GSON自定义序列化程序,用于带有“收集”字段的对象

gson嵌套的自定义序列化程序

自定义反序列化器仅适用于json.NET的某些字段

在自定义JsonConverter中反序列化嵌套对象列表

自定义JSON反序列化程序,用于格式错误的JSON

无法使用Scala Circle json库中的LocalDateTime的自定义解码器反序列化对象

自定义JsonConverter不适用于WebAPI对象反序列化

Gson自定义反序列化器,用于String类

序列化json对象中的自定义对象

序列化器:自定义嵌套关系

Django:自定义对象json序列化

如何自定义JSON对象序列化?

Jackson-仅将自定义反序列化器用于特定的JSON

手动打开可序列化对象的自定义检查器

在 ember 序列化器上定义自定义根 json 节点

Spring Boot - 使用自定义对象数组 JSON 序列化自定义对象

在 Jackson 中使用自定义序列化程序序列化嵌套对象时出现 JsonGenerationException

JSON 使用嵌套的自定义对象序列化 dict

自定义类的对象列表的json序列化

使用自定义反序列化器 Jackson 将 .json 文件转换为 Java 对象

Ktor自定义json对象反序列化

JSON.Net - 如何反序列化自定义类型的嵌套字段