将JSON字典反序列化为具有属性的对象

时间:2018-07-18 12:19:36

标签: c# json json.net

我陷入了糟糕的API,该API返回以下JSON:

{
   "root":[
      {
         "row":[
            {
               "name":"Foo",
               "value":"Some value"
            },
            {
               "name":"Bar",
               "value":"Some other value"
            }, (...)
         ]
      },
      {
         "row":[
            {
               "name":"Foo",
               "value":"Lorem"
            },
            {
               "name":"Bar",
               "value":"Ipsum"
            }, (...)
         ]
      }, (...)
   ]
}

我想使用Newtonsoft.Json将其反序列化为C#对象列表,以便名称与对象属性匹配,而值将为属性值。该类如下所示:

class Row
{
    public string Foo { get; set; }
    public string Bar { get; set; }
    (...)
}

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

您可以使用自定义JsonConverter来处理此问题。在一个简单的示例下面,它需要进行一些null检查等,但这可以实现这个想法:

    public class RowConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(Row[]);
        }

        public override bool CanWrite => false;

        public override bool CanRead => true;

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {

            if (reader.TokenType == JsonToken.Null)
            {
                return string.Empty;
            }
            else if (reader.TokenType == JsonToken.String)
            {
                return serializer.Deserialize(reader, objectType);
            }
            else
            {
                JObject obj = JObject.Load(reader);
                var root = obj["root"];
                if (root != null)
                {
                    var rows = new List<Row>();
                    foreach (var item in root)
                    {
                        var row = item["row"];
                        var newRow = new Row();
                        foreach(var field in row)
                        {
                            // better use reflection here to convert name-value to property setter
                            if (field.Value<string>("name") == "Foo")
                            {
                                newRow.Foo = field["value"].Value<string>();
                            }

                            if (field.Value<string>("name") == "Bar")
                            {
                                newRow.Bar = field["value"].Value<string>();
                            }
                        }

                        rows.Add(newRow);
                    }

                    return rows.ToArray();
                }
                return null;
            }
        }

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

然后在Row类上:

[JsonConverter(typeof(RowConverter))]
public class Row
{
    public string Foo { get; set; }

    public string Bar { get; set; }
}

如果需要将其包含在MVC中,请在Startup.cs(asp.net核心)中:

services
    .AddMvc()
    .AddJsonOptions(options => { options.SerializerSettings.Converters.Add(new RowConverter()); });

答案 1 :(得分:0)

作为一种选择,您可以将其转换为单个“行”属性的字典:

var values = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);

在创建动态对象之后:

private static dynamic DictionaryToObject(IDictionary<String, Object> dictionary)  
{  
    var expandoObj = new ExpandoObject();  
    var expandoObjCollection = (ICollection<KeyValuePair<String, Object>>)expandoObj;  

    foreach (var keyValuePair in dictionary)  
    {  
        expandoObjCollection.Add(keyValuePair);  
    }  
    dynamic eoDynamic = expandoObj;  
    return eoDynamic;  
}  

private static T DictionaryToObject<T>(IDictionary<String, Object> dictionary) where T : class  
{  
    return DictionaryToObject(dictionary) as T;  
}  

答案 2 :(得分:-1)

您可以创建如下所示的类,然后使用newtosnsoft

public class root
{
    public List<row> row {get;set;}

}

public class row
{
   public string name {get;set;}
   public string value {get;set;}
}