简体   繁体   English

如何将值列表反序列化为 C# 对象

[英]How to deserialize a list of values to C# objects

My application receives a JSON object as:我的应用程序收到一个 JSON 对象:

{
  "names": [
    "name_1",
    "name_2"
  ]
}

I want to deserialize it to a list of Person object, defined as:我想将其反序列化为Person对象列表,定义为:

class Person
{
    public string Name { set; get; }
}

Currently, I am deserializing the JSON object to a list of strings then create a list of Person manually like the following:目前,我正在将 JSON 对象反序列化为一个字符串列表,然后手动创建一个Person列表,如下所示:

var names = JsonConvert.DeserializeObject<List<string>>(json);
var people = new List<Person>();
foreach(var name in names)
    people.Add(new Person(){ Name = name });

Instead, I am interested in something like the following:相反,我对以下内容感兴趣:

var people = JsonConvert.DeserializeObject<List<Person>>(json);

I am implementing the Person deserializer as:我正在将Person反序列化器实现为:

public class PersonJsonConverter : JsonConverter
{
    private readonly Dictionary<string, string> _propertyMappings;

    public PersonJsonConverter()
    {
        _propertyMappings = new Dictionary<string, string>
        {
            {"name", nameof(Person.Name)}
        };
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType.GetTypeInfo().IsClass;
    }

    public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        object instance = Activator.CreateInstance(objectType);
        var props = objectType.GetTypeInfo().DeclaredProperties.ToList();

        JObject obj = JObject.Load(reader);
        foreach (JProperty jsonProperty in obj.Properties())
        {
            if (!_propertyMappings.TryGetValue(jsonProperty.Name, out var name))
                name = jsonProperty.Name;

            PropertyInfo prop = props.FirstOrDefault(
                pi => pi.CanWrite && pi.Name == name);

            prop?.SetValue(
                instance,
                jsonProperty.Value.ToObject(prop.PropertyType, serializer));
        }

        return instance;
    }
}

This deserializer can deserilize object such as:这个反序列化器可以反序列化对象,例如:

{
  "names": [
    "name": "name_1",
    "name": "name_2"
  ]
}

but not但不是

{
  "names": [
    "name_1",
    "name_2"
  ]
}

Note that my application can receive both types of JSON objects, so better to have a common deserializer for both types.请注意,我的应用程序可以接收两种类型的 JSON 对象,因此最好为这两种类型拥有一个通用的反序列化器。

You have to deserialize names to something like a JArray , then foreach each entry with a new Person('name') .您必须将names反序列化为JArray类的JArray ,然后使用new Person('name')每个条目进行foreach The JSON as you received it just doesn't match your desired schema.您收到的 JSON 与您想要的架构不匹配。 You have to manually transform it.您必须手动转换它。

Please try below:请尝试以下:

class Person
{
    public string Name { set; get; }
}

public class PersonJsonConverter : JsonConverter
{
    // private readonly Dictionary<string, string> _propertyMappings;

    public PersonJsonConverter()
    {
        /*_propertyMappings = new Dictionary<string, string>
        {
            {"name", nameof(Person.Name)}
        };*/
    }

    public override bool CanConvert(System.Type objectType)
    {
        return objectType.GetTypeInfo().IsClass;
    }

    public override object ReadJson(JsonReader reader, System.Type objectType, object existingValue, JsonSerializer serializer)
    {
        object instance = Activator.CreateInstance(objectType);
        // List<T> implements the non-generic IList interface
        IList list = (IList)instance;
        var typeInfo = objectType.GetTypeInfo();
        var props = typeInfo.DeclaredProperties.ToList();
        PropertyInfo prop = props.FirstOrDefault(pi => pi.PropertyType == typeof(Person));

        JObject obj = JObject.Load(reader);
        var namesArray = obj["names"]; // you can use this instead of for loop on obj.Properties.
        /*foreach (JProperty jsonProperty in obj.Properties())
        {
            if (jsonProperty.Name == "names")
            {
                var namesArray = JArray.Parse(jsonProperty.Value.ToString());
                */
                if (namesArray.Type == JTokenType.Array && prop != null)
                {
                    foreach (var ja in namesArray)
                    {
                        object personInstance = Activator.CreateInstance(prop.PropertyType);
                        PropertyInfo personNamePropInfo = prop.PropertyType.GetProperty(nameof(Person.Name));
                        personNamePropInfo.SetValue(personInstance,
                            Convert.ChangeType(ja, personNamePropInfo.PropertyType), null);
                        list.Add(personInstance); // Whatever you need to add
                    }
                }

          /*      break;
            }
        }*/

        return instance;
    }

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

and use it like below:并像下面一样使用它:

var samplejson = @"{
  ""names"": [
    ""name_1"",
    ""name_2""
  ]
}";
var obj = JsonConvert.DeserializeObject<List<Person>>(samplejson,   new JsonConverter[] { new PersonJsonConverter() });

The other json does not seem to be valid json.另一个 json 似乎不是有效的 json。 在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM