【问题标题】:Deserializing string encoded JSON反序列化字符串编码的 JSON
【发布时间】:2021-10-22 05:17:42
【问题描述】:

有没有办法正确反序列化以双引号开头和结尾的 JSON 字符串?

数据以流的形式传入(来自 AWS S3 对象)。这是流的内容(注意开头和结尾的双引号):

"[{\"startTime\":1610396717400,\"eventCode\":44,\"eventParam\":5},{\"startTime\":1610396717700,\"eventCode\":81,\"eventParam\":56},{\"startTime\":1610396717800,\"eventCode\":44,\"eventParam\":4}]"

JsonSerializer 似乎没有正确反序列化它。但是,对于以下内容,它可以按预期工作:

[{"startTime":1610396717400,"eventCode":44,"eventParam":5},{"startTime":1610396717700,"eventCode":81,"eventParam":56}]

这是sn-p:

public class ControllerEventJson
{
    [JsonProperty("startTime")]
    public long StartTime { get; set; }

    [JsonProperty("eventCode")]
    public int EventCode { get; set; }

    [JsonProperty("eventParam")]
    public int EventParam { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        // stream is a MemoryStream
        using (StreamReader sr = new StreamReader(stream))
        using (JsonTextReader reader = new JsonTextReader(sr))
        {
            // Required for large JSON objects to avoid errors when streaming
            reader.SupportMultipleContent = true;

            JsonSerializer serializer = new JsonSerializer();
            while (reader.Read())
            {
                // Deserialize each object in array individually
                if (reader.TokenType == JsonToken.StartObject)
                {
                    var obj = serializer.Deserialize<ControllerEventJson>(reader);
                    // Do something with obj
                }
            }
        }
    }
}

【问题讨论】:

  • 基本上将值反序列化为 JSON 令牌,你会得到一个字符串,也就是你要反序列化的 JSON 数组。 (它已经被有效地双重编码了。)你有什么理由以流媒体方式这样做吗?使用File.ReadAllText 阅读内容会更简单,除非它真的很大。
  • 您拥有的是一个 JSON 对象,编码为 JSON 字符串。你的问题的答案是“首先反序列化字符串,然后反序列化结果”,你的问题的实际解决方案是没有双重序列化开始。 为什么是那个格式的字符串?
  • @JonSkeet 数据将以流的形式进入。在此示例中,我将其简化为打开文件,但 JSON 文件存储在 AWS S3 中。我正在使用他们的 API 将 ResponseStream 复制到 MemoryStream like so
  • @Jungl:如果您已经将整个内容读入内存,那么在response.ResponseStream 周围创建一个StreamReader 并在其上调用ReadToEnd 以获取整个JSON 会更简单一个字符串。
  • @JonSkeet 谢谢,我最终这样做是为了得到整个字符串。然后修剪引号的末端并使用 JsonConvert.DeserializeObject 取回一个列表。

标签: c# json.net


【解决方案1】:

你可以试试这个。这个已经在 Visual Studio 中测试过并且可以正常工作

Dictionary<string, string> items = null;
var list = new List<Dictionary<string, string>>();
    ...... your code
    using (JsonTextReader reader = new JsonTextReader(sr))
    {
        reader.SupportMultipleContent = true;

        Item item = null;
        while (reader.Read())
        {
            switch (reader.TokenType)
            {
                case JsonToken.StartArray:
                 items = new Dictionary<string, string>();
                    continue;

                case JsonToken.StartObject:
                    item = new Item();
                    break;

                case JsonToken.PropertyName:
                    item.Key = reader.Value.ToString();
                    break;

                case JsonToken.EndObject:
                    list.Add(items);
                    items = new Dictionary<string, string>();
                    break;

                case JsonToken.Integer:
                    item.Value = reader.Value.ToString();
                    if (item != null) items.Add(item.Key, item.Value);
                    item = new Item();
                    break;
            }
        }
    }

    var json = JsonConvert.SerializeObject(list);
    var jd = JsonConvert.DeserializeObject(json, typeof( List<ControllerEventJson>));

结果

[
  {
    "startTime": 1610396717400,
    "eventCode": 44,
    "eventParam": 5
  },
  {
    "startTime": 1610396717700,
    "eventCode": 81,
    "eventParam": 56
  },
  {
    "startTime": 1610396717800,
    "eventCode": 44,
    "eventParam": 4
  }
]

public class Item
{
    public string Key { get; set; }
    public string Value { get; set; }
}

    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 2023-03-23
    • 2021-09-02
    • 2013-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多