如何在C#中将Json数组转换为对象列表

18

我有以下的Json字符串

 {
"JsonValues":{

        "id": "MyID",

         "values": {
            "value1":{
                "id": "100",
                "diaplayName": "MyValue1"
            },
            "value2":{
                "id": "200",
                "diaplayName": "MyValue2"
            }
       }
}
}

我想要将Json字符串转换为下面的类

  class ValueSet
   {
    [JsonProperty("id")]
    public string id
    {
        get;
        set;
    }
    [JsonProperty("values")]
    public List<Value> values
    {
        get;
        set;
    }
  }

class Value
{
    public string id
    {
        get;
        set;
    }
    public string DiaplayName
    {
        get;
        set;
    }
}

我的反序列化代码是

JavaScriptSerializer js = new JavaScriptSerializer();
        StreamReader sr = new StreamReader(@"ValueSetJsonString.txt");
        string jsonString = sr.ReadToEnd();
        var items = JsonConvert.DeserializeObject<ValueSet>(jsonString);

但是我在序列化后得到了null值,我该怎么解决?


请查看此解决方案: https://dev59.com/42Uq5IYBdhLWcg3wY_ka - Nyweron
9个回答

22

正如其他人已经指出的那样,你没有得到预期结果的原因是你的 JSON 不符合你尝试反序列化的类结构。你需要更改你的 JSON 或者更改你的类。由于其他人已经展示了如何更改 JSON,所以我将在这里采取相反的方法。

为了匹配你在问题中发布的 JSON,你的类应该像下面这样定义。请注意,我做了以下更改:

  1. 我添加了一个与你的 JSON 中外部对象对应的 Wrapper 类。
  2. 我将 ValueSet 类的 Values 属性从 List<Value> 更改为 Dictionary<string, Value>,因为你的 JSON 中的 values 属性包含一个对象,而不是一个数组。
  3. 我添加了一些额外的 [JsonProperty] 属性,以匹配你的 JSON 对象中的属性名。

类定义:

class Wrapper
{
    [JsonProperty("JsonValues")]
    public ValueSet ValueSet { get; set; }
}

class ValueSet
{
    [JsonProperty("id")]
    public string Id { get; set; }
    [JsonProperty("values")]
    public Dictionary<string, Value> Values { get; set; }
}

class Value
{
    [JsonProperty("id")]
    public string Id { get; set; }
    [JsonProperty("diaplayName")]
    public string DisplayName { get; set; }
}

您需要反序列化到Wrapper类,而不是ValueSet类。然后您可以从Wrapper获取ValueSet

var valueSet = JsonConvert.DeserializeObject<Wrapper>(jsonString).ValueSet;

这里是一个可行的程序示例:

class Program
{
    static void Main(string[] args)
    {
        string jsonString = @"
        {
            ""JsonValues"": {
                ""id"": ""MyID"",
                ""values"": {
                    ""value1"": {
                        ""id"": ""100"",
                        ""diaplayName"": ""MyValue1""
                    },
                    ""value2"": {
                        ""id"": ""200"",
                        ""diaplayName"": ""MyValue2""
                    }
                }
            }
        }";

        var valueSet = JsonConvert.DeserializeObject<Wrapper>(jsonString).ValueSet;

        Console.WriteLine("id: " + valueSet.Id);
        foreach (KeyValuePair<string, Value> kvp in valueSet.Values)
        {
            Console.WriteLine(kvp.Key + " id: " + kvp.Value.Id);
            Console.WriteLine(kvp.Key + " name: " + kvp.Value.DisplayName);
        }
    }
}

这里是输出结果:

id: MyID
value1 id: 100
value1 name: MyValue1
value2 id: 200
value2 name: MyValue2

(jsonString).ValueSet; 后缀就解决了我的问题! - 27k1

12

http://json2csharp.com/

我发现上述链接非常有用,因为它通过从实际返回的JSON生成C#类来纠正了我的代码。

然后我调用:

JsonConvert.DeserializeObject<RootObject>(jsonString); 

一切都按预期顺利运作。


1
谢谢你提供的链接,要是我几周前就看到它就好了,那样可以省下我几天痛苦的工作! - guytz72
1
我一直在为一个简单的JSON字符串中的列表而苦恼。你的链接解决了我的问题。非常感谢!!! - Zath
https://app.QuickType.io类似,但具有更多功能和较少的广告。他们还为Visual Studio提供了插件。(我与他们无关) - Caius Jard

6

您是否确认该行代码正常工作且字符串中包含值?

string jsonString = sr.ReadToEnd();

如果是,请尝试使用以下代码替换最后一行代码:

ValueSet items = JsonConvert.DeserializeObject<ValueSet>(jsonString);

如果您有一个由JSON组成的数组,您可以使用以下代码将其转换为列表:

List<ValueSet> items = JsonConvert.DeserializeObject<List<ValueSet>>(jsonString);

祝您好运!


2

您的数据结构与JSON不匹配。

您的JSON如下:

{
    "JsonValues":{
        "id": "MyID",
        ...
    }
}

但是你要序列化的数据结构是这样的:

class ValueSet
{
    [JsonProperty("id")]
    public string id
    {
        get;
        set;
    }
    ...
}

您正在跳过一步:您的JSON是一个类,它有一个名为JsonValues的属性,该属性的值是您的ValueSet数据结构的对象。

此外,在您的类内部,您的JSON如下:

"values": { ... }

你的数据结构是这样的:
[JsonProperty("values")]
public List<Value> values
{
    get;
    set;
}

注意,在 JSON 中,{ .. } 定义了一个对象,而 [ .. ] 定义了一个数组。所以根据你的 JSON,你没有一堆值,但是你有一个包含类型为 Value 的属性 value1value2one 值对象。
由于反序列化器期望得到一个数组,但实际上得到了一个对象,它执行了最少破坏性(异常)的操作:跳过该值。因此,你的属性 values 仍保持其默认值:null
如果可以的话,请调整你的 JSON。以下 JSON 将匹配你的数据结构,很可能是你实际想要的:
{
    "id": "MyID",

     "values": [
         {
            "id": "100",
            "diaplayName": "MyValue1"
         }, {
            "id": "200",
            "diaplayName": "MyValue2"
         }
     ]
}

我已经更改了JSON结构,但仍然在对象中获取到null值。 - niknowj
我疏忽了。请注意,在您的 C# 代码中,您有 DiaplayName,但在您的 JSON 中,您有 diaplayName。名称是区分大小写的。要么更改 C# 中的属性名称,JSON 中的名称,或使用 JsonPropertyAttribute 来告诉序列化程序您属性的 JSON 名称。 - user2674389
1
在StackOverflow上,更加精确地描述错误总是更好的选择。你得到了“对象中的null值” - 究竟是什么null值?整个对象?你的列表?一个单独的属性?哪个属性?你越精确,人们就越容易帮助你(也许你甚至会自己发现错误)。 - user2674389

1

将Json转换为C#类 = https://json2csharp.com/json-to-csharp

在模式出现后

        WebClient client = new WebClient();

        client.Encoding = Encoding.UTF8;

        string myJSON = client.DownloadString("http://xxx/xx/xx.json");

        var valueSet = JsonConvert.DeserializeObject<Root>(myJSON);

我们最大的错误之一是无法将类结构与json匹配。
这个连接会自动处理。稍后您将编写它 ;) = https://json2csharp.com/json-to-csharp 就是这样。

这个答案基本上与bultorious的答案完全相同,只是发布时间早了4年。OP已经有了json,他们不需要使用旧的WebClient(我们现在有HttpClientt)来检索代码片段,其余的答案是“使用json2csharp”,这已经被发布过了。请不要添加重复的答案。 - Caius Jard

0

这个函数将JsonElement反序列化为对象列表。

List<object> draftInvoices = JsonConvert.DeserializeObject<List<object>>(jsonDrafts.ToString());

例子:

[HttpPost]
        [Route("CreateDraft")]
        public async Task<IActionResult> CreateDraft([FromBody] JsonElement jsonDrafts)
        {
            List<object> draftInvoices = JsonConvert.DeserializeObject<List<object>>(jsonDrafts.ToString());
             
          
                for (int i = 0; i < draftInvoices.Count; i++) 
                 {
                  ........
                 }  

0

你有一个不匹配的 jSon 字符串,如果你想将其转换为列表,请尝试这个方法

{
    "id": "MyID",

     "values": [
        {
            "id": "100",
            "diaplayName": "MyValue1",
        },
        {
            "id": "200",
            "diaplayName": "MyValue2",
        }
   ]    
}

谢谢。我已经像这样更改了JSON字符串,但仍然得到空值。 - niknowj

0

这也是可能的:

using System.Web.Helpers;
var listOfObjectsResult = Json.Decode<List<DataType>>(JsonData);

-4

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