web-dev-qa-db-ja.com

エンティティのシリアル化時にJson.Netの予期しない文字( "\")

優れたJson.Netライブラリを使用して、エンティティフレームワークによって生成されたエンティティをシリアル化しています。そのために次のコードを使用します。

using (MyVoucherEntities context = new MyVoucherEntities())
{
  List<MyObject> list = context.MyObjects.ToList();
  string json = JsonConvert.SerializeObject(list);
}

すべてがうまくいく、つまり、オブジェクトは正しくシリアル化されます。ただし、クライアント側で逆シリアル化するときに悪夢を見せるエスケープ文字「\」が追加されます。

 [
     {
         \"$id\": \"1\",
         \"CreationDate\": \"\\\/Date(1293186324257+0000)\\\/\",
        \"ImageUrl\": \"http:\/\/www.google.com\",
         \"Title\": \"Here is a title\"
     } ]

なぜ、どのようにしてこれらのエスケープ文字スラッシュ「\」を取り除くことができるのか誰かが知っていますか?

23
Renaud

文字列にエスケープ文字が含まれている理由を見つけました("\")。オブジェクトをシリアル化した後、WCFを介してJSON文字列をクライアントアプリに返します。どうやら、WCFはネットワークに送信する前に、これらの文字を文字列に自動的に追加しています。これはデフォルトの動作であり、明らかに必須です。

これらのエスケープ文字は必要なかったので、回避策はサービスの戻り値の型をStreamに変更して、メモリストリーム内にJSON文字列を返すことです。それは完全に動作し、非常に高速です。

17
Renaud

実際にはエスケープ文字をまったく追加していないのではないかと思います。デバッガで文字列を見ているだけで、エスケープを追加するthat'sだと思います。

ファイルまたはコンソールにダンプしてみてください。

31
Jon Skeet

オブジェクトのリストをシリアル化した結果が配列であるため、これは無効なJSONです。つまり、jsonは[で始まり、]で終わります。これを修正するには、オブジェクトのリストをルートオブジェクト(クラスのインスタンスまたは匿名オブジェクト)でラップする必要があるため、結果の文字列は{で始まり、}で終わります。

例えば:

var output = new List<object>();
var json = JsonConvert.SerializeObject(new { root = output }, Formatting.Indented);
Response.Write(json);
3
Jone Polvora

私はあなたが出力されたものを完全に引用していないことに注意する必要があります(私はあなたの答えで動作するURLを得ました-それは答えとしてではなくあなたの質問に編集されるべきでした)。私がファイルに戻した文字列はこれでした:

"[{\"$id\":\"1\",\"CreationDate\":\"\\\/Date(1293186324257+0000)\\\/\",\"ImageUrl\":\"http:\/\/www.c-tina.com\/MyVoucherAdmin\/Images\/shop22\/burger.jpg\",\"Title\":\"Get one burger for free\",\"Description\":\"Bla lbzlfpzkfgmzke\\rdmjdgmj\\r\\r\\rlgfpzkegmkzepk\",\"ShopId\":22,\"PromotionId\":15,\"Shop\":null,\"Features\":[],\"SingleStats\":[],\"WhatsHots\":[],\"EntityKey\":{\"$id\":\"2\",\"EntitySetName\":\"Promotions\",\"EntityContainerName\":\"MyVoucherEntities\",\"EntityKeyValues\":[{\"Key\":\"PromotionId\",\"Type\":\"System.Int32\",\"Value\":\"15\"}]}}]"

私にとって重要なことは、先頭と末尾にエスケープされていない引用符があり、出力されているものはすべて引用符で囲む必要があると判断し、引用符で囲んでいる場合は、その中にある引用符をエスケープする必要があるということです。

完全な出力を確認しないと、JSONを生成するために上記で引用したコードに問題があるのか​​、これを処理する後のステップで問題が発生し、それが引用の原因になっているのかどうかはわかりません。デバッグして、シリアライズ呼び出しの出力が後の段階で実行されるのではなく、エスケープされたバージョンを確実に生成していることを確認しましたか?デバッガーに慣れていない場合は、Jon Skeetがファイルまたはコンソールにダンプすることを推奨していることに注意して、そのような混乱がないことを確認してください。

1
Chris

これは役に立ちますか?私はそれをWebServiceで使用してJsonコンテンツを返しました:

private HttpContent ConvertToJsonContent(object content)
{
  string jsonObject = JsonConvert.SerializeObject(content, Newtonsoft.Json.Formatting.Indented);
  return new StringContent(jsonObject, Encoding.UTF8, "application/json");
}

文字列に「\」がある場合、2つの「\\」が返されます。 Unescapeを使用することでこれを回避できます

private HttpContent ConvertToJsonContent(object content)
{
  string jsonObject = Regex.Unescape(JsonConvert.SerializeObject(content, Newtonsoft.Json.Formatting.Indented));
  return new StringContent(jsonObject, Encoding.UTF8, "application/json");
}
1
Mickey Mouse