将属性映射到对象列表

3

我有一个JSON数据,看起来像这样:

{
    "Item1": {
        "Field1": "Val1",
        "Field2": "Val2"
    },
    "Item2": {
        "Field1": "Val11",
        "Field2": "Val22"
    },
    ....
    "ItemN": {
        "Field1": "Val1",
        "Field2": "Val2"
    },
}

我需要将它反序列化为一组类,看起来像这样:
public class Root
{
    public Item Item1;
    public Item Item2;

    public List<Item> Items; // << all the Items should go here
}

public class Item
{
    public string Field1;
    public string Field2;
}

如何在反序列化时使Newtonsoft.Json按此方式映射数据?

你的 JSON 应该被组成为一个数组,这样才能正常工作。 - Travis J
实际上,这个问题可以被视为2017年那些问题的重复。难道字典不可接受吗?如果您需要使用 List<Item> ,那么是否需要在某处捕获 "ItemN" 名称,或者它们可以被丢弃? - dbc
4个回答

11

不需要 Root 类。我会反序列化为一个字典。

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

你能稍微修改一下吗?它将如何将JS对象数组映射到字典中,反序列化会做什么? - Zeeshan Adil

7
如果您需要从JSON中的相同数据填充Items列表和Root类中显示的各个Item属性,那么您将需要一个自定义的JsonConverter来完成。以下转换器应该可以工作:
public class RootConverter : 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);
        var root = new Root();

        // populate all known Root properties 
        serializer.Populate(obj.CreateReader(), root);

        // populate Items list with all objects that can be converted to an Item
        root.Items = obj.Properties()
                        .Where(p => p.Value.Type == JTokenType.Object && 
                                    (p.Value["Field1"] != null || p.Value["Field2"] != null))
                        .Select(p => p.Value.ToObject<Item>())
                        .ToList();
        return root;
    }

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

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

然后要使用它,需要在 Root 类上添加一个 [JsonConverter] 属性,就像这样:

[JsonConverter(typeof(RootConverter))]
public class Root
{
    public Item Item1 { get; set; }
    public Item Item2 { get; set; }

    public List<Item> Items; // << all the Items should go here
}

沙盒: https://dotnetfiddle.net/aADhzw


我确实需要根类来静态映射一些属性。 - user626528
我想知道是否有任何方法可以不手动进行属性映射? - user626528
当然,你可以使用 Populate;请查看更新的答案。 - Brian Rogers

2

如果您需要使用根对象进行工作,可以尝试以下方法:

public class Root : Dictionary<string, Item>
{
    public List<Item> Items => this.Values.ToList();
}

然后,您可以将JSON反序列化为根对象:
 var root = JsonConvert.DeserializeObject<Root>(json);

-3

使用:

public class Root
{
    public List<Item> Items {get;set;}
}
public class Item
{
    public string Field1 {get;set;}
    public string Field2; {get;set;}
}

关于类和调用:

Root foobar = new JavaScriptSerializer().Deserialize<Root>(result);

进行反序列化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接