通过 JSON.NET 解析动态 JSON 数据
Parse dynamic JSON data via JSON.NET
我有一套格式有趣的 JSON,我需要使用 C# 阅读,在我的例子中特别使用 JSON.NET
,尽管这可能使用 System.Text.Json
来完成还有。
数据的结构类似于:
[
{
"Name": "Name A",
"Value": "Apples"
},
{
"Name": "Name B",
"Value": {
"key1": "value1",
"key2": "value2"
}
}
]
简而言之,数组对象的形状有些不同,具体来说'Value' 属性是变化的。我只对具有 key/value (Dictionary<string, string>
) 类型值数据的记录感兴趣,如果有帮助的话。
将此数据读入某种类型表示的最佳(在本例中是最简单的)方法是什么?我说打字是因为这是我想要使用的,但这不是 严格 的要求。
类似“嘿JSON.NET,请给我所有 'Value' 类型为 key/value 的记录,如果可能的话,作为一个对象结构,其中值被具体化作为类型化的 Dictionary 对象。如果有帮助,其他记录可能会被丢弃。谢谢! ".
如果能以某种方式使用 POCO 对象来实现,那就太好了。
试试这个
var jsonParsed = JArray.Parse(json);
var items = new List<Item>();
foreach (JObject item in jsonParsed)
{
var name = string.Empty;
foreach (var prop in item.Properties())
{
if (prop.Value.Type.ToString() != "Object")
{
if (prop.Name == "Name") name = (string)prop.Value;
continue;
}
items.Add(new Item
{
Name = name,
Value = prop.Value.ToObject<Dictionary<string, string>>()
});
}
}
结果
[
{
"Name": "Name B",
"Value": {
"key1": "value1",
"key2": "value2"
}
}
]
class
public class Item
{
public string Name { get; set; }
public Dictionary<string, string> Value { get; set; }
}
一种可能的方法是使用 JsonConverter
子类。
这可能例如如果找到 JTokenType.Object
,则包含 Dictionary<string, string>
和 key-value 对,而 return 在任何其他情况下都是空字典。当然可以根据需要定制。
DictionaryValueConverter
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class DictionaryValueConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Dictionary<string, string>));
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue,
JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
return token.Type == JTokenType.Object
? token.ToObject<Dictionary<string, string>>()
: new Dictionary<string, string>();
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
项目
你的数组的 Item
看起来像这样:
using Newtonsoft.Json;
public class Item
{
public string Name { get; set; }
[JsonConverter(typeof(DictionaryValueConverter))]
public Dictionary<string, string> Value { get; set; }
}
测试
你可以这样称呼它:
using Newtonsoft.Json;
public static class Program
{
static void Main()
{
string json = @"
[
{
""Name"": ""Name A"",
""Value"": ""Apples""
},
{
""Name"": ""Name B"",
""Value"": {
""key1"": ""value1"",
""key2"": ""value2""
}
}
]
";
var list = JsonConvert.DeserializeObject<List<Item>>(json);
if (list == null) return;
foreach (var item in list)
{
Console.WriteLine($"name: {item.Name}");
if (item.Value.Count == 0)
{
Console.WriteLine("no value");
}
foreach (var (key, value) in item.Value)
{
Console.WriteLine($" -> Key = {key}, Value = {value}");
}
Console.WriteLine();
}
}
}
以上示例代码的输出为:
name: Name A
no value
name: Name B
-> Key = key1, Value = value1
-> Key = key2, Value = value2
如上所述,可以根据需要自定义方法。
我有一套格式有趣的 JSON,我需要使用 C# 阅读,在我的例子中特别使用 JSON.NET
,尽管这可能使用 System.Text.Json
来完成还有。
数据的结构类似于:
[
{
"Name": "Name A",
"Value": "Apples"
},
{
"Name": "Name B",
"Value": {
"key1": "value1",
"key2": "value2"
}
}
]
简而言之,数组对象的形状有些不同,具体来说'Value' 属性是变化的。我只对具有 key/value (Dictionary<string, string>
) 类型值数据的记录感兴趣,如果有帮助的话。
将此数据读入某种类型表示的最佳(在本例中是最简单的)方法是什么?我说打字是因为这是我想要使用的,但这不是 严格 的要求。
类似“嘿JSON.NET,请给我所有 'Value' 类型为 key/value 的记录,如果可能的话,作为一个对象结构,其中值被具体化作为类型化的 Dictionary
如果能以某种方式使用 POCO 对象来实现,那就太好了。
试试这个
var jsonParsed = JArray.Parse(json);
var items = new List<Item>();
foreach (JObject item in jsonParsed)
{
var name = string.Empty;
foreach (var prop in item.Properties())
{
if (prop.Value.Type.ToString() != "Object")
{
if (prop.Name == "Name") name = (string)prop.Value;
continue;
}
items.Add(new Item
{
Name = name,
Value = prop.Value.ToObject<Dictionary<string, string>>()
});
}
}
结果
[
{
"Name": "Name B",
"Value": {
"key1": "value1",
"key2": "value2"
}
}
]
class
public class Item
{
public string Name { get; set; }
public Dictionary<string, string> Value { get; set; }
}
一种可能的方法是使用 JsonConverter
子类。
这可能例如如果找到 JTokenType.Object
,则包含 Dictionary<string, string>
和 key-value 对,而 return 在任何其他情况下都是空字典。当然可以根据需要定制。
DictionaryValueConverter
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class DictionaryValueConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Dictionary<string, string>));
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue,
JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
return token.Type == JTokenType.Object
? token.ToObject<Dictionary<string, string>>()
: new Dictionary<string, string>();
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
项目
你的数组的 Item
看起来像这样:
using Newtonsoft.Json;
public class Item
{
public string Name { get; set; }
[JsonConverter(typeof(DictionaryValueConverter))]
public Dictionary<string, string> Value { get; set; }
}
测试
你可以这样称呼它:
using Newtonsoft.Json;
public static class Program
{
static void Main()
{
string json = @"
[
{
""Name"": ""Name A"",
""Value"": ""Apples""
},
{
""Name"": ""Name B"",
""Value"": {
""key1"": ""value1"",
""key2"": ""value2""
}
}
]
";
var list = JsonConvert.DeserializeObject<List<Item>>(json);
if (list == null) return;
foreach (var item in list)
{
Console.WriteLine($"name: {item.Name}");
if (item.Value.Count == 0)
{
Console.WriteLine("no value");
}
foreach (var (key, value) in item.Value)
{
Console.WriteLine($" -> Key = {key}, Value = {value}");
}
Console.WriteLine();
}
}
}
以上示例代码的输出为:
name: Name A
no value
name: Name B
-> Key = key1, Value = value1
-> Key = key2, Value = value2
如上所述,可以根据需要自定义方法。