如何使用json.NET反序列化动态命名的根节点 [英] How to deserialize a dynamically named root node with json.NET

查看:52
本文介绍了如何使用json.NET反序列化动态命名的根节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是json文件的示例:

This is an example of the json file:

{
   "John Smith": {
      "id": "72389",
      "email": "johnsmith@gmail.com",
      "books": [
         {
            "id": "0",
            "title": "The Hunger Games",
            "rating": "5"
         },
         {
            "id": "1",
            "title": "Harry Potter and the Order of the Phoenix",
            "rating": "3"
         },
      ],
      "magazines": [
         {
            "id": "2",
            "title": "National Geographic",
            "rating": "1"
         },
         {
            "id": "3",
            "title": "Wired",
            "rating": "4"
         }
      ],
   }
}

请注意,根节点有一个动态名称(John Smith),并且我需要反序列化的每个json都有一个不同的名称. 此json结构要求具有如下设置的类:

Notice the root node has a dynamic name (John Smith), and every json I need to deserialize will have a different name. This json structure would require to have classes setup as follows:

public class RootObject
{
    public JohnSmith { get; set; }
}

public class JohnSmith //oops
{
    public string id { get; set; }
    public string email { get; set; }
    public List<Book> books { get; set; }
    public List<Magazine> magazines { get; set; }
}

public class Book
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

public class Magazine
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

我的目标是反序列化绕过/忽略"根对象,最重要的是动态地命名节点.这不是很关键,但是我希望能够获得姓氏并将其设置为Person类的一个属性.

My goal is to deserialize "bypassing/ignoring" root object and most importantly that dynamicaly named node. This is not crucial, but I would like to be able to get the last name and set as a property on the Person class.

public class Person
{
    public string id { get; set; }
    public string email { get; set; }
    public string name { get; set; }
    public List<Book> books { get; set; }
    public List<Magazine> magazines { get; set; }
}

public class Book
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

public class Magazine
{
    public string id { get; set; }
    public string title { get; set; }
    public string rating { get; set; }
}

这是我现在的操作方式:

Here is how I am doing this now:

var jo = JObject.Parse(json);
var deserializable = jo.First.First.ToString();

string name;
var jp = (JProperty)jo.First;
if (jp != null) name = jp.Name;

var person = JsonConvert.DeserializeObject<Person>(deserializable);
person.name = name;

这可以正常工作,但是我想知道,也许可以通过使用自定义JsonConverter来做得更好?恐怕这对我的自动取款机来说有点过头了,所以我想在这里寻求帮助...

This works OK, but I was wondering, maybe it could be done better by using a custom JsonConverter? I'm afraid this is a little bit over my head atm, so I am asking here for some help...

无论如何,如果有更好的方法可以实现这一目标,请分享.

Anyway, if there is any better way to achieve this, please share.

推荐答案

我将保留解决方案的第一部分(反序列化为JObject),但不会进行其他序列化.我的代码如下:

I would keep the first part of your solution (deserializing to JObject), but I wouldn't do another serialization. My code would look like this:

var jo = JObject.Parse(json);
var jp = jo.Properties().First();
var name = jp.Name;
var person = jp.Value.ToObject<Person>();

如果需要自定义转换器,可以使用以下代码.转换器将您的对象转换为Person的列表,其中每个属性代表另一个Person.

In case you want a custom converter, you could use the following code. The converter converts your object to a list of Persons where every property represents another Person.

class PersonListConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var list = (PersonList) value;

        writer.WriteStartObject();

        foreach (var p in list.Persons)
        {
            writer.WritePropertyName(p.Name);
            serializer.Serialize(writer, p);
        }

        writer.WriteEndObject();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jo = serializer.Deserialize<JObject>(reader);
        var result = new PersonList();
        result.Persons = new List<Person>();

        foreach (var prop in jo.Properties())
        {
            var p = prop.Value.ToObject<Person>();
            // set name from property name
            p.Name = prop.Name;
            result.Persons.Add(p);
        }

        return result;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(PersonList);
    }
}

PersonList的位置如下所示:

[JsonConverter(typeof(PersonListConverter))]
class PersonList
{
    public List<Person> Persons { get; set; }
}

这篇关于如何使用json.NET反序列化动态命名的根节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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