如何反序列化狡猾的 JSON(带有不正确引用的字符串和缺少括号)? [英] How to deserialize dodgy JSON (with improperly quoted strings, and missing brackets)?

查看:37
本文介绍了如何反序列化狡猾的 JSON(带有不正确引用的字符串和缺少括号)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不得不解析(并最终重新序列化)一些不可靠的 JSON.它看起来像这样:

I am having to parse (and ultimately reserialize) some dodgy JSON. it looks like this:

{
  name: "xyz",
  id: "29573f59-85fb-4d06-9905-01a3acb2cdbd",
  status: "astatus",
  color: colors["Open"]
},
{
  name: "abc",
  id: "29573f59-85fb-4d06-9905-01a3acb2cdbd",
  status: "astatus",
  color: colors["Open"]
}

这里有很多问题 - 从最严重的开始.

There are a number of problems here - starting with the most severe.

  1. 颜色:颜色["打开"]

甚至是WTF?如果我去掉颜色",那么我可以得到一个字符串数组,但我不能调整到开箱即用.

WTF even is that? If I drop 'colors' then I can get an array of strings out but I can't tweak to work out of the box.

是一个没有方括号的数组.我可以通过包裹它们来解决这个问题.但是有没有办法支持开箱即用?

It is an array without square brackets. I can fix this by wrapping in them. But is there a way to support out of the box?

属性没有引号.反序列化对这些很好..但重新序列化只是没有骰子.

Properties have no quotes. Deserializing is fine for these.. but reserializing is just no dice.

有什么建议可以处理这个结构的内部和外部吗?

Any suggestions of handling both in and out of this structure?

推荐答案

按顺序回答您的问题 #1 - #3:

Answering your questions #1 - #3 in order:

  1. Json.NET 不支持以 colors["Open"] 形式读取不可靠的属性值(正如您正确指出的,这违反了 JSON 标准).

  1. Json.NET does not support reading dodgy property values in the form colors["Open"] (which, as you correctly note, violates the JSON standard).

相反,您需要手动修复这些值,例如通过某种Regex:

Instead, you will need to manually fix these values, e.g. through some sort of Regex:

var regex = new Regex(@"(colors\[)(.*)(\])");
var fixedJsonString = regex.Replace(jsonString, 
    m => string.Format(@"""{0}{1}{2}""", m.Groups[1].Value, m.Groups[2].Value.Replace("\"", "\\\""), m.Groups[3].Value));

这会将 color 属性值更改为正确转义的 JSON 字符串:

This changes the color property values into properly escaped JSON strings:

color: "colors[\"Open\"]"

但是,

Json.NET 确实能够通过调用 JsonWriter.WriteRawValue() 来自 自定义JsonConverter.

Json.NET does, however, have the capability to write dodgy property values by calling JsonWriter.WriteRawValue() from within a custom JsonConverter.

定义以下转换器:

public class RawStringConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string);
    }

    public override bool CanRead { get { return false; } }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var s = (string)value;
        writer.WriteRawValue(s);
    }
}

然后定义您的 RootObject 如下:

Then define your RootObject as follows:

public class RootObject
{
    public string name { get; set; }
    public string id { get; set; }
    public string status { get; set; }

    [JsonConverter(typeof(RawStringConverter))]
    public string color { get; set; }
}

然后,当重新序列化时,您将在 JSON 中获得原始的可疑值.

Then, when re-serialized, you will get the original dodgy values in your JSON.

10.0.3.请参阅问题 1396问题 1355 了解详情.您需要设置 JsonTextReader.SupportMultipleContent = true 使其工作.

Support for deserializing comma-delimited JSON without outer brackets will be in the next release of Json.NET after 10.0.3. see Issue 1396 and Issue 1355 for details. You will need to set JsonTextReader.SupportMultipleContent = true to make it work.

与此同时,作为一种解决方法,您可以从 如何将多个 TextReader 串在一起? by Rex M 并用括号 [] 将您的 JSON 括起来.

In the meantime, as a workaround, you could grab ChainedTextReader and public static TextReader Extensions.Concat(this TextReader first, TextReader second) from the answer to How to string multiple TextReaders together? by Rex M and surround your JSON with brackets [ and ].

因此,您将按如下方式反序列化您的 JSON:

Thus you would deserialize your JSON as follows:

List<RootObject> list;
using (var reader = new StringReader("[").Concat(new StringReader(fixedJsonString)).Concat(new StringReader("]")))
using (var jsonReader = new JsonTextReader(reader))
{
    list = JsonSerializer.CreateDefault().Deserialize<List<RootObject>>(jsonReader);
}

(或者你可以手动用 [] 包围你的 JSON 字符串,但我更喜欢不涉及复制可能大的字符串的解决方案.)

(Or you could just manually surround your JSON string with [ and ], but I prefer solutions that don't involve copying possibly large strings.)

如果您使用自己的 JsonTextWriterCloseOutput = false.您还可以手动将每个序列化项之间的 , 写入每个 JsonTextWriter 共享的底层 TextWriter.

Re-serializing a root collection without outer braces is possible if you serialize each item individually using its own JsonTextWriter with CloseOutput = false. You can also manually write a , between each serialized item to the underlying TextWriter shared by every JsonTextWriter.

如果您设置 JsonTextWriter.QuoteName = false.

Serializing JSON property names without a surrounding quote character is possible if you set JsonTextWriter.QuoteName = false.

因此,要重新序列化您的 List 而不带引号的属性名称或外括号,请执行以下操作:

Thus, to re-serialize your List<RootObject> without quoted property names or outer braces, do:

var sb = new StringBuilder();
bool first = true;
using (var textWriter = new StringWriter(sb))
{
    foreach (var item in list)
    {
        if (!first)
        {
            textWriter.WriteLine(",");
        }
        first = false;
        using (var jsonWriter = new JsonTextWriter(textWriter) { QuoteName = false, Formatting = Formatting.Indented, CloseOutput = false })
        {
            JsonSerializer.CreateDefault().Serialize(jsonWriter, item);
        }
    }
}

var reserializedJson = sb.ToString();

示例 .Net fiddle 展示了这一切的实际效果.

Sample .Net fiddle showing all this in action.

这篇关于如何反序列化狡猾的 JSON(带有不正确引用的字符串和缺少括号)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆