【问题标题】:Parse JSON with indexes in property name to list使用属性名称中的索引解析 JSON 以列出
【发布时间】:2021-03-09 03:11:38
【问题描述】:

处理与此类似的 JSON 响应,其中一些响应可能多达 500 多个项目。

{
    "name1": "Paul",
    "address1": "123 paul lane",
    "name2": "George",
    "address2": "123 george lane",
    "name3": "Howie",
    "address3": "123 howie lane"
}

我想要一种方法,最好使用某种 JSON 反序列化,将其塞入以下对象的列表中。

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}

我不反对编写自定义反序列化器,但我正在处理很多此类响应,此处可重用的解决方案是理想的。

【问题讨论】:

  • 如果可能的话,我会反对这一点。看起来它是由某人在需求上读取“输出 JSON”并且毫无意义地实现的。将响应固定为可序列化为 Person 的集合的合理 JSON 输出。否则,@Stanislas 在下面有一个合理的答案。
  • @McAden 我很想反击,但这是提供此数据的第三方。不过我同意。这种格式更难使用,我想他们更难用这种方式编写它。

标签: c# json .net-5


【解决方案1】:

这看起来确实是一个格式非常糟糕的 JSON。

我的方法将取决于 JSON 中字段的可预测性,但如果它是没有模式的无穷无尽的键值对列表,我可能会尝试将其完全转换为那个。

大型 JSON

文件大小不同,您的方法会有所不同,具体取决于您可以使用多少内存来解析此文件。

使用 Newtonsoft.Json

Read JSON with JsonTextReader

string json = "{\"name1\": \"Paul\",\"address1\": \"123 paul lane\",\"name2\": \"George\",\"address2\": \"123 george lane\",\"name3\": \"Howie\",\"address3\": \"123 howie lane\"}";
using var reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StringReader(json));
while (reader.Read())
{
    switch (reader.TokenType)
    {
        case Newtonsoft.Json.JsonToken.PropertyName:
        case Newtonsoft.Json.JsonToken.String:
            Console.WriteLine($"{reader.TokenType} - {reader.Value}");
            break;
        default:
            Console.WriteLine($"Skipped: {reader.TokenType}");
            break;
    }
}

使用 System.Text.Json

Use Utf8JsonReader

string json = "{\"name1\": \"Paul\",\"address1\": \"123 paul lane\",\"name2\": \"George\",\"address2\": \"123 george lane\",\"name3\": \"Howie\",\"address3\": \"123 howie lane\"}";
var data = System.Text.Encoding.UTF8.GetBytes(json);
var reader = new System.Text.Json.Utf8JsonReader(data);
while (reader.Read())
{
    switch (reader.TokenType)
    {
        case System.Text.Json.JsonTokenType.PropertyName:
        case System.Text.Json.JsonTokenType.String:
            Console.WriteLine($"{reader.TokenType} - {reader.GetString()}");
            break;
        default:
            Console.WriteLine($"Skipped: {reader.TokenType}");
            break;
    }
}

输出

上面两个例子都会输出:

Skipped: StartObject
PropertyName - name1
String - Paul
PropertyName - address1
String - 123 paul lane
PropertyName - name2
String - George
PropertyName - address2
String - 123 george lane
PropertyName - name3
String - Howie
PropertyName - address3
String - 123 howie lane
Skipped: EndObject

小 JSON

使用 Newtonsoft.Json

如果 JSON 文件很小,您可以将整个文件解析为 JObject 并像这样遍历它。

private static IEnumerable<KeyValuePair<string, string>> GetPairs()
{
    string json = "{\"name1\": \"Paul\",\"address1\": \"123 paul lane\",\"name2\": \"George\",\"address2\": \"123 george lane\",\"name3\": \"Howie\",\"address3\": \"123 howie lane\"}";
    var data = Newtonsoft.Json.Linq.JObject.Parse(json);
    foreach (var pair in data)
    {
        yield return new KeyValuePair<string, string>(pair.Key, pair.Value.ToString());
    }
}

更好的方法可能是使用JTokenReader,但我以前没有使用过。

使用 System.Text.Json

我相信 System.Text.Json 中的 Newtonsoft.Json.Linq.JObject 的等价物是 JsonDocument
Use JsonDocument for access to data

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2021-11-13
    • 1970-01-01
    • 1970-01-01
    • 2016-05-04
    相关资源
    最近更新 更多