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

时间:2016-04-07 11:17:15

标签: c# json serialization json.net

我从第三方系统获得了一些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)相当大,但对于某些正则表达式/查找替换解决方案而言不是太大,如果真的有必要(b)不在我的控制之下,所以我无法更改格式。我确定答案已经在StackOverflow上了,但我发现很难找到合适的搜索条件......

3 个答案:

答案 0 :(得分:3)

你试过了吗?

extract = extract.Replace("\\","\\\\");
解析字符串之前

答案 1 :(得分:2)

基本问题是,在JSON字符串文字中,the escaped solidus "\/" means exactly the same as the unescaped solidus "/"和Json.NET以非常低的级别解析和解释这种转义,即JsonTextReader.ReadStringIntoBuffer()。因此,没有办法让更高级别的代码检测并记住字符串文字是否格式化为"\/Date(2015-02-02)\/""/Date(2015-02-02)/",然后根据需要回写一个或另一个。

如果您可以总是将额外的转义添加到以/Date(开头并以)/开头的字符串,则可以使用{{3}的自定义子类这样做:

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);
        }
    }
}

然后用你当前正在做的JsonTextWriter解析:

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)\/"
}

答案 2 :(得分:0)

我希望这可以提供帮助,在JSON中序列化日期:

http://www.newtonsoft.com/json/help/html/datesinjson.htm