具有数据类型的Json.NET自定义JsonConverter [英] Json.NET Custom JsonConverter with data types

查看:42
本文介绍了具有数据类型的Json.NET自定义JsonConverter的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无意中发现了一个以以下格式输出JSON的服务:

{
    "Author": "me",
    "Version": "1.0.0",
    "data.Type1": {
        "Children": [
            {
                "data.Type1": {
                    "Children": [
                        {
                            "data.Type2": {
                                "name": "John",
                                "surname": "Doe"
                            }
                        }
                    ]
                }
            },
            {
                "data.Type3": {
                    "dob": "1990-01-01"
                }
            }
        ]
    }
}
数据类型名称保留为属性名称,它们的值是实际的对象。它们都以data.前缀开头。

事后我想得到的是这样的:

{ // Root
    "Author": "me",
    "Version": "1.0.0",
    "Children": [ // Type1
        {
            "Children": [ // Type1
                { // Type2
                    "Name": "John",
                    "Surname": "Doe"
                }
            ]
        },
        { // Type3
            "DoB": "1990-01-01"
        }
    ]
}

包含以下类:

class Type1 {
    ICollection<object> Children { get; set; }
}

class Type2 {
    public string Name { get; set; }
    public string Surname { get; set; }
}

class Type3 {
    public DateTime DoB { get; set; }
}

class Root 
{
    public string Author { get; set; }
    public string Version { get; set; }
    public Type1 Children { get; set; }
}

问题

如何将其反序列化为添加的C#类,同时考虑数据类型并将其从树中删除?

我已尝试使用自定义JsonConverter,但正在努力解决如何动态选择转换器的问题,因为最简单的方法是将属性放在属性上,但不支持该属性。

一个小示例就足够了。

json

虽然此推荐答案格式有些不寻常,并且由于动态属性名称而拒绝使用属性,但仍然可以通过一个小更改将其反序列化为您的首选类结构:我建议您将Root类中的Children属性更改为ICollection<object>,以镜像Type1类中的Children属性现在,它与所需输出的结构不匹配(其中Children显示为数组,而不是对象),否则将需要转换器中的其他代码才能正确处理。

class Root
{
    public string Author { get; set; }
    public string Version { get; set; }
    public ICollection<object> Children { get; set; }
}

以下是我为转换器设计的内容(假设进行了上述更改):

class CustomConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Root));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);
        Root root = new Root();
        root.Author = (string)obj["Author"];
        root.Version = (string)obj["Version"];
        root.Children = ((Type1)DeserializeTypeX(obj, serializer)).Children;
        return root;
    }

    private object DeserializeTypeX(JObject obj, JsonSerializer serializer)
    {
        JProperty prop = obj.Properties().Where(p => p.Name.StartsWith("data.")).First();
        JObject child = (JObject)prop.Value;
        if (prop.Name == "data.Type1")
        {
            List<object> children = new List<object>();
            foreach (JObject jo in child["Children"].Children<JObject>())
            {
                children.Add(DeserializeTypeX(jo, serializer));
            }
            return new Type1 { Children = children };
        }
        else if (prop.Name == "data.Type2")
        {
            return child.ToObject<Type2>(serializer);
        }
        else if (prop.Name == "data.Type3")
        {
            return child.ToObject<Type3>(serializer);
        }
        throw new JsonSerializationException("Unrecognized type: " + prop.Name);
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

使用此转换器,您可以反序列化为您的类,如下所示:

Root root = JsonConvert.DeserializeObject<Root>(json, new CustomConverter());

然后可以序列化到新格式,如下所示:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    DateFormatString = "yyyy-MM-dd",
    Formatting = Formatting.Indented
};

Console.WriteLine(JsonConvert.SerializeObject(root, settings));

小提琴:https://dotnetfiddle.net/ESNMLE

这篇关于具有数据类型的Json.NET自定义JsonConverter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆