反序列化 JSON 没有唯一 属性 名称
Deserializing JSON Without Unique Property Name
我有一个 json 字符串,如下所示
{
"1ST": {
"name": "One",
"symbol": "1st"
},
"2ND": {
"name": "Two",
"symbol": "2nd"
}
}
我正在尝试将其序列化为 C# 对象。看起来它正在创建一个字典,所以我创建了以下结构
public class Response
{
public Dictionary<string, Item> Objects { get; set; }
}
public class Item
{
public string name { get; set; }
public string symbol { get; set; }
}
并且在序列化期间 运行 以下
response = JsonConvert.DeserializeObject<Response>(jsonString);
它不会在反序列化时抛出错误,但我的响应只是返回 null。我错过了什么?
建议使用强类型对象,但另一种方法是您可以使用将在运行时评估的动态类型。
请看下面的代码。
请注意,我更改了变量名,因为我们不能在 C# 中定义以数字开头的变量。
using Newtonsoft.Json;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var jsonString = @"{
'First': {
'name': 'One',
'symbol': '1st'
},
'Second': {
'name': 'Two',
'symbol': '2nd'
}
}";
//If you want to access using strong type.
var response = JsonConvert.DeserializeObject<Response>(jsonString);
var secondSymbol = response.Second.symbol.ToString();
System.Console.WriteLine(secondSymbol);
//If you want to access using dynamic type, will evalute in runtime.
var responseDynamic = JsonConvert.DeserializeObject<dynamic>(jsonString);
var secondSymbolDynamic = responseDynamic.Second.symbol.ToString() ;
System.Console.WriteLine(secondSymbolDynamic);
System.Console.ReadLine();
}
public class Response
{
public Item First { get; set; }
public Item Second { get; set; }
}
public class Item
{
public string name { get; set; }
public string symbol { get; set; }
}
}
}
希望有用。 :)
你的基本想法是正确的,但你还有一个你并不真正想要的额外 Objects
属性:你的 JSON 有效地是 字典。您可以将其直接反序列化为 Dictionary<string, Item>>
。这是一个例子:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
public class Item
{
public string Name { get; set; }
public string Symbol { get; set; }
public override string ToString() => $"{Name}/{Symbol}";
}
public class Test
{
static void Main()
{
var json = File.ReadAllText("test.json");
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, Item>>(json);
foreach (var entry in dictionary)
{
Console.WriteLine($"{entry.Key}: {entry.Value}");
}
}
}
输出:
1ST: One/1st
2ND: Two/2nd
现在如果您需要您的Response
类型,有多种选择:
- 从
Dictionary<string, Item>
派生并删除 Objects
属性。 (如果你需要 Objects
属性 就不好了。)
- 反序列化到字典,然后创建一个新的
Response
对象并自己分配 属性。 (如果响应是另一种类型的一部分则不好。)
- 调查 Json.NET 是否有一些属性将
Objects
视为一种 "root" 属性.
我在最后一个方面有 一些 运气,但不是一个完整的解决方案。如果您将 Objects
更改为 Dictionary<string, JToken>
,那么您可以将 [JsonExtensionData]
应用于它,这使得它充当任何不匹配的 属性 的默认字典。但是,我还没有找到说服 Json.NET 使用该属性 和 执行适当转换的方法。您可以创建一个字典,每次向其中添加条目时执行从 JToken
到 Item
的转换(使用常规 Json.NET 代码),然后将该值添加到另一个字典 - 但是那太丑了。这可能只是 Json.NET 无法处理的情况。
我有一个 json 字符串,如下所示
{
"1ST": {
"name": "One",
"symbol": "1st"
},
"2ND": {
"name": "Two",
"symbol": "2nd"
}
}
我正在尝试将其序列化为 C# 对象。看起来它正在创建一个字典,所以我创建了以下结构
public class Response
{
public Dictionary<string, Item> Objects { get; set; }
}
public class Item
{
public string name { get; set; }
public string symbol { get; set; }
}
并且在序列化期间 运行 以下
response = JsonConvert.DeserializeObject<Response>(jsonString);
它不会在反序列化时抛出错误,但我的响应只是返回 null。我错过了什么?
建议使用强类型对象,但另一种方法是您可以使用将在运行时评估的动态类型。
请看下面的代码。
请注意,我更改了变量名,因为我们不能在 C# 中定义以数字开头的变量。
using Newtonsoft.Json;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var jsonString = @"{
'First': {
'name': 'One',
'symbol': '1st'
},
'Second': {
'name': 'Two',
'symbol': '2nd'
}
}";
//If you want to access using strong type.
var response = JsonConvert.DeserializeObject<Response>(jsonString);
var secondSymbol = response.Second.symbol.ToString();
System.Console.WriteLine(secondSymbol);
//If you want to access using dynamic type, will evalute in runtime.
var responseDynamic = JsonConvert.DeserializeObject<dynamic>(jsonString);
var secondSymbolDynamic = responseDynamic.Second.symbol.ToString() ;
System.Console.WriteLine(secondSymbolDynamic);
System.Console.ReadLine();
}
public class Response
{
public Item First { get; set; }
public Item Second { get; set; }
}
public class Item
{
public string name { get; set; }
public string symbol { get; set; }
}
}
}
希望有用。 :)
你的基本想法是正确的,但你还有一个你并不真正想要的额外 Objects
属性:你的 JSON 有效地是 字典。您可以将其直接反序列化为 Dictionary<string, Item>>
。这是一个例子:
using System;
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
public class Item
{
public string Name { get; set; }
public string Symbol { get; set; }
public override string ToString() => $"{Name}/{Symbol}";
}
public class Test
{
static void Main()
{
var json = File.ReadAllText("test.json");
var dictionary = JsonConvert.DeserializeObject<Dictionary<string, Item>>(json);
foreach (var entry in dictionary)
{
Console.WriteLine($"{entry.Key}: {entry.Value}");
}
}
}
输出:
1ST: One/1st
2ND: Two/2nd
现在如果您需要您的Response
类型,有多种选择:
- 从
Dictionary<string, Item>
派生并删除Objects
属性。 (如果你需要Objects
属性 就不好了。) - 反序列化到字典,然后创建一个新的
Response
对象并自己分配 属性。 (如果响应是另一种类型的一部分则不好。) - 调查 Json.NET 是否有一些属性将
Objects
视为一种 "root" 属性.
我在最后一个方面有 一些 运气,但不是一个完整的解决方案。如果您将 Objects
更改为 Dictionary<string, JToken>
,那么您可以将 [JsonExtensionData]
应用于它,这使得它充当任何不匹配的 属性 的默认字典。但是,我还没有找到说服 Json.NET 使用该属性 和 执行适当转换的方法。您可以创建一个字典,每次向其中添加条目时执行从 JToken
到 Item
的转换(使用常规 Json.NET 代码),然后将该值添加到另一个字典 - 但是那太丑了。这可能只是 Json.NET 无法处理的情况。