2016-04-07 18 views
1

値にバックスラッシュを含むサードパーティシステムのJSONがあります。C#形式値のバックスラッシュ ''付きのJSON

文字列に対応するエスケープC#の文字列無し
string extract = @"{""key"": ""\/Date(2015-02-02)\/""}"; 

:例えば

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

I(例えばインデント)このJSONをフォーマットできるようにしたいです。

一般的にフォーマットするために、私はそうのようなJsonConvertのようなものを使用することがあります:

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

これはかなりのない作業を行い、それが日付として値を見ていると、それは標準のMS形式ではありませんように\/Date(ticks)\/、それは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の上ですでに確信しているが、私はそれが困難な右の検索用語を見つけるために探しています...

+0

文字列 – derloopkat

答えて

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(と終わりで始まる文字列に逃げる余分を追加してOKであれば、あなたがこれを行うには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); 

この版画:

C#の二重のバックスラッシュで
{ 
    "key": "\/Date(2015-02-02)\/" 
} 
0

私はこれが役立つことを願って、JSONの日付シリアル化:

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

+0

にバックスラッシュを表すために使用されているこれは、2つの日付のコンバータについての詳細与えます - 私のJSON文字列にはかなりものですどちらもが。あなたが私の場合に役立つだろうと思っていたこのページの特定のものがありますか? – jlb83

2

あなたは試しましたか?

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

文字列を解析する前に?

+0

これは機能しますが、面倒です。正確に言えば、次のようにしてジョブを終了します.JsonConvert.SerializeObject(JsonConvert.DeserializeObject(extract.Replace( "\\"、 "\\\\")、settings)、Formatting.Indented) .Replace( "\\\\"、 "\\") ' – jlb83

+0

はい、少し面倒ですが、入力の複雑さを考慮に入れて、私はあなたがこの解決策または類似のものを使用することを余儀なくされると思われます。バックスラッシュは時にはシリアライズ/解析が難しい場合があります。 –