C# 格式的 JSON 值为反斜杠''



我有一些来自第三方系统的JSON,它在值中包含反斜杠。例如:

string extract = @"{""key"": ""/Date(2015-02-02)/""}";

没有c#字符串转义的字符串对应于字符串:

{"key": "/Date(2015-02-02)/"}

我希望能够格式化(例如缩进)这个JSON。

通常,对于格式化,我可能会使用类似JsonConvert的东西:

JsonConvert.SerializeObject(JsonConvert.DeserializeObject(extract), Formatting.Indented)

这并不完全有效,因为它将值视为一个日期,但由于它不是/Date(ticks)/的标准MS格式,因此它将变为1970年1月1日的日期:

{
  "key": "1970-01-01T00:00:02.015+00:00"
}

下一种方法是使用序列化程序设置不转换日期(我不在乎它是否将字段识别为日期,尽管稍后可能会很方便):

JsonSerializerSettings settings = new JsonSerializerSettings
{
    DateParseHandling = DateParseHandling.None,
};
JsonConvert.SerializeObject(JsonConvert.DeserializeObject(extract, settings), Formatting.Indented);

在反序列化过程中,这似乎将反斜杠视为转义符,因此一旦我看到最终结果,它就会"丢失":

{
  "key": "/Date(2015-02-02)/"
}

有没有一种方法可以在C#中格式化JSON(带或不带JsonConvert),从而在值中保留反斜杠?

请注意,我正在处理的真正JSON(a)相当大,但对于某些regex/find-replace-解决方案来说不太大,如果真的有必要的话(b)不在我的控制范围内,所以我无法更改格式。我确信答案已经在StackOverflow上了,但我发现很难找到正确的搜索词。。。

您尝试过吗:

extract = extract.Replace("\","\\");

在解析字符串之前?

基本问题是,在JSON字符串文字中,转义的solidus "/"与未转义的solidus"/"的含义完全相同,JSON.NET在非常低的级别(即JsonTextReader.ReadStringIntoBuffer())解析和解释这种转义。因此,更高级别的代码无法检测和记住字符串文字是格式化为"/Date(2015-02-02)/"还是"/Date(2015-02-02)/",然后根据需要写回其中一个。

如果您同意总是向以/Date(开头、以)/结尾的字符串添加额外的转义,则可以使用JsonTextWriter的自定义子类来执行此操作:

public class DateLiteralJsonTextWriter : JsonTextWriter
{
    public DateLiteralJsonTextWriter(TextWriter writer) : base(writer) { }
    public override void WriteValue(string value)
    {
        const string startToken = @"/Date(";
        const string replacementStartToken = @"/Date(";
        const string endToken = @")/";
        const string replacementEndToken = @")/";
        if (value != null && value.StartsWith(startToken) && value.EndsWith(endToken))
        {
            var sb = new StringBuilder();
            // Add the initial quote.
            sb.Append(QuoteChar);
            // Add the new start token.
            sb.Append(replacementStartToken);
            // Add any necessary escaping to the innards of the "/Date(.*)/" string.
            using (var writer = new StringWriter(sb))
            using (var jsonWriter = new JsonTextWriter(writer) { StringEscapeHandling = this.StringEscapeHandling, Culture = this.Culture, QuoteChar = '"' })
            {
                var content = value.Substring(startToken.Length, value.Length - startToken.Length - endToken.Length);
                jsonWriter.WriteValue(content);
            }
            // Strip the embedded quotes from the above.
            sb.Remove(replacementStartToken.Length + 1, 1);
            sb.Remove(sb.Length - 1, 1);
            // Add the replacement end token and final quote.
            sb.Append(replacementEndToken);
            sb.Append(QuoteChar);
            // Write without any further escaping.
            WriteRawValue(sb.ToString());
        }
        else
        {
            base.WriteValue(value);
        }
    }
}

然后使用DateParseHandling = DateParseHandling.None进行解析,就像您当前所做的那样:

var settings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None };
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
using (var jsonWriter = new DateLiteralJsonTextWriter(writer) { Formatting = Formatting.Indented})
{
    JsonSerializer.CreateDefault(settings).Serialize(jsonWriter,  JsonConvert.DeserializeObject(extract, settings));
}
Console.WriteLine(sb);

此打印:

{
  "key": "/Date(2015-02-02)/"
}

相关内容

  • 没有找到相关文章