2015-09-29 16 views
8

ASP.NET Web APIアプリケーションでは、私が扱っているモデルの中には、クライアントサイドでのみ有用な特別なJSONのチャンクが含まれています。サーバー上では、文字列としてリレーショナルデータベースに出入りするだけです。パフォーマンスが重要であり、JSON文字列サーバー側を処理することは意味がないようです。Json.NET - すでにシリアル化されたプロパティの再シリアル化を防止する

だから、C#で、このようなオブジェクトを想像:デフォルトでは

new Person 
{ 
    FirstName = "John", 
    LastName = "Smith", 
    Json = "{ \"Age\": 30 }" 
}; 

を、Json.NETはこのように、このオブジェクトをシリアル化します:

{ 
    "FirstName": "John", 
    "LastName": "Smith", 
    "Json": "{ \"Age\": 30 }" 
} 

私が指示できるようにしたいと思いますJson.NETはJsonプロパティが既にシリアル化された表現であると仮定しているため、再シリアル化しないでください。結果のJSONは次のようになります。

{ 
    "FirstName": "John", 
    "LastName": "Smith", 
    "Json": { 
     "Age": 30 
    } 
} 

理想的には、これは両方向で機能します。すなわち、JSON表現をポストすると、上のC#表現に自動的に逆シリアル化されます。

Json.NETでこれを達成するための最良のメカニズムは何ですか?カスタムJsonConverterが必要ですか?より単純な属性ベースのメカニズムがありますか?効率性の問題。全体のポイントは、シリアル化オーバーヘッドをスキップすることですはマイクロ最適化のビットであることができますが、議論のためにそうではないと仮定しよう。 (潜在的にかさばるJsonのプロパティが返されると、大きなリストがあります。)

+0

プロパティ 'Json'が文字列の場合は、文字列としてシリアル化する必要があります。私は問題が何であるか完全にはわからない。それを文字列としてシリアル化し、データベースに文字列として格納し、それを文字列として逆直列化します。 –

+0

たぶん私はそれをうまく説明しませんでした。私はデフォルトで何が起きるのかと私が達成しようとしているものとの違いを強調する余分なJSONサンプルを追加しました。 –

+1

サーバーサイドのコードがJSON文字列を制御できる場所から取得している場合は、この問題を解決するよりも、その部分を修正するほうがずっと良いでしょう。しかし、あなたがアクセスできないものから来ている場合、私が最初に試みるのは、それを取得したソースから取得したときにそれを逆シリアル化することです。これはカスタムデシリアライザで行うことができます。あなたのために最高の解決策を考え出すための情報が不足しています。 – krillgar

答えて

13

あなたは、あなたが希望する結果を得るでしょうJRawstringからPersonJsonプロパティのタイプを変更することができるならば。

public class Person 
{ 
    public string FirstName { get; set;} 
    public string LastName { get; set;}   
    public JRaw Json { get; set;} 
} 

また、あなたがstring財産を維持し、直列化のためのプロキシとして使用するJRawプロパティ追加することができます。いずれかの方法を

public class Person 
{ 
    public string FirstName { get; set;} 
    public string LastName { get; set;} 
    [JsonIgnore] 
    public string Json { get; set; } 

    [JsonProperty("Json")] 
    private JRaw MyJson 
    { 
     get { return new JRaw(this.Json); } 
     set { this.Json = value.ToString(); } 
    }   
} 

をあなたが要求したとして、シリアライズとデシリアライズの両方が動作します。

+2

「JRaw」について私は知らなかったし、私が解決しようとしているものに最も適しているようだ。ありがとう。 –

+0

FWIWは、この回答のために、私はこの質問が他の「すでに尋ねられている」質問を参照するものでなければならないと考えます。 – HeyZiko

1

私は、これは正確に行うために有用なものであるわからないんだけど、あなたは、このようなカスタムコンバータを作成できます。

public class StringToJsonConverter : JsonConverter 
{ 
    public override bool CanConvert(Type t) 
    { 
     throw new NotImplementedException(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var o = JsonConvert.DeserializeObject(value.ToString()); 
     serializer.Serialize(writer,o); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var o = serializer.Deserialize(reader); 
     return JsonConvert.SerializeObject(o); 
    } 
} 

var obj = new Person 
{ 
    FirstName = "John", 
    LastName = "Smith", 
    Json = "{ \"Age\": 30 }" 
}; 

var s = JsonConvert.SerializeObject(obj); 

をそして、この取得:あなたは[JsonConverter(typeof(StringToJsonConverter))]であなたにJsonプロパティを飾る場合さて、あなたはこれを行うことができます

はここしかし、私のバイオリンで、私はラウンドシリアライズとデシリアライズをトリップてるfiddle

一つのノートだが、Jsonプロパティの値はまったく同じではありません。どうして?あなたの中括弧の周りの余分なスペースは、プロセス中に取り除かれているためです。もちろん、それらは重要ではありません。

+0

ダウン投票者の説明には注意してください?それはOPが求めるものを正確に達成します。 –

+0

私はそれが私ではないことを伝えることができます:) –

+0

それは働いた(+1)。しかし、あなたのところでは、私は有用性に疑問を持ち始めています。プロパティはサーバー上の文字列として存在する必要があるだけで、生の要求からデータベースへの変換や逆もあります。シリアル化/デシリアライズをまったく含まないソリューションが必要でした。しかし、親オブジェクトのプロパティとして、私はそれが可能ではない、あるいは努力する価値がないと思っています。 –

0

シリアライズの一部をスキップする方法があるかどうかわかりません。シリアライズとデシリアライズを単純な方法で行うオプションがあります。

public class Person 
{ 
    public string FirstName = "John"; 
    public string LastName = "Smith"; 
    [JsonIgnore] 
    public string Json = "{ \"Age\": 30 }"; 
    public JObject JsonP { get { return JsonConvert.DeserializeObject<JObject>(Json); } } 
} 
関連する問題