【问题标题】:How can I deserialize an invalid json ? Truncated list of objects如何反序列化无效的 json ?截断的对象列表
【发布时间】:2016-04-12 14:54:37
【问题描述】:

我的 json 文件主要是一个包含对象的数组,但列表不完整,所以我不能使用最后一个条目。我想反序列化文件的其余部分,同时丢弃最后一个无效条目

[ { "key" : "value1" }, { "key " : "value2"}, { "key 

请告诉我是否有使用 Newtonsoft.Json 库的方法,或者我是否需要一些预处理。

谢谢!

【问题讨论】:

  • JSON 不是 HTML,没有充分的理由让库实现无效数据的变通方法。您可能正在使用计算机语言来处理 JSON;使用这种语言(C#?)的字符串操作函数实现预处理应该不难。

标签: json json.net


【解决方案1】:

看起来在 Json.NET 8.0.3 上,您可以将字符串从 JsonTextReader 流式传输到 JTokenWriter,并通过捕获并吞下解析截断的 JSON 时抛出的 JsonReaderException 来获得部分结果:

JToken root;
string exceptionPath = null;
using (var textReader = new StringReader(badJson))
using (var jsonReader = new JsonTextReader(textReader))
using (JTokenWriter jsonWriter = new JTokenWriter())
{
    try
    {
        jsonWriter.WriteToken(jsonReader);
    }
    catch (JsonReaderException ex)
    {
        exceptionPath = ex.Path;
        Debug.WriteLine(ex);
    }
    root = jsonWriter.Token;
}

Console.WriteLine(root);
if (exceptionPath != null)
{
    Console.WriteLine("Error occurred with token: ");
    var badToken = root.SelectToken(exceptionPath);
    Console.WriteLine(badToken);
}

这会导致:

[
  {
    "key": "value1"
  },
  {
    "key ": "value2"
  },
  {}
]

然后您可以使用JToken.ToObject 完成对部分对象的反序列化。您也可以使用badToken.Remove() 删除不完整的数组条目。

最好不要一开始就生成无效的 JSON。我也不完全确定这是 Json.NET 的记录功能,因此它可能不适用于 Json.NET 的未来版本。 (例如,可以想象 Newtonsoft 可以更改他们的算法,使得 JTokenWriter.Token 仅在写入成功时设置。)

【讨论】:

    【解决方案2】:

    您可以使用 JsonReader 类并尝试尽可能地解析。下面的代码将解析尽可能多的属性,然后抛出异常。这当然是你想反序列化成一个具体的类。

    public Partial FromJson(JsonReader reader)
    {
        while (reader.Read())
        {
            // Break on EndObject
            if (reader.TokenType == JsonToken.EndObject)
                break;
    
            // Only look for properties
            if (reader.TokenType != JsonToken.PropertyName)
                continue;
    
            switch ((string) reader.Value)
            {
                case "Id":
                    reader.Read();
                    Id = Convert.ToInt16(reader.Value);
                    break;
    
                case "Name":
                    reader.Read();
                    Name = Convert.ToString(reader.Value);
                    break;
    
            }
        }
    
        return this;
    }
    

    代码取自CGbR JSON Target

    【讨论】:

      【解决方案3】:

      上面的第二个答案真的很好很简单,帮了我!

              static string FixPartialJson(string badJson)
              {
                  JToken root;
                  string exceptionPath = null;
                  using (var textReader = new StringReader(badJson))
                  using (var jsonReader = new JsonTextReader(textReader))
                  using (JTokenWriter jsonWriter = new JTokenWriter())
                  {
                      try
                      {
                          jsonWriter.WriteToken(jsonReader);
                      }
                      catch (JsonReaderException ex)
                      {
                          exceptionPath = ex.Path;                    
                      }
                      root = jsonWriter.Token;
                  }
      
                  return root.ToString();            
              }
      

      【讨论】:

        猜你喜欢
        • 2017-07-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多