2012-02-28 15 views
18

Json.Netを使用しているとき、$ typeプロパティをレンダリングされたjsonに取得する方法を理解していますが、そのフィールド名を変更する方法はありますか?私は "$ type"の代わりに "__type"を使う必要があります。

+0

[JSON-LD](http://json-ld.org)は '@ type'を使用しています –

答えて

12

これは、public const string TypePropertyName = "$type";Newtonsoft.Json.Serialization.JsonTypeReflectorにハードコードされていますが、内部の静的なクラスです。

私はこれを自分で必要としました。私が考えることができるのは、json.net自体のカスタム修正バージョンを持つことだけです。もちろん、これは大きなピタです。

+4

残念ながら、私はかなり残念ながら私が完全に経路を断念しなければならなかったので、多くの場合、Json.Netがどれほど難しいかを使用することになります。これは単なる一例です。 –

+0

私は自分自身がサーバー側でどのように私はC#で書かれ、Json.NETを使用して、ジャクソンを使用してAndroidアプリから送信されたJSONを非直列化できるかを見ています。ジャクソンでは "$ type"を使うように設定できますが、とにかく動作しません。 – Ted

13

http://json.codeplex.com/workitem/22429

"私はむしろ、ハードコード化され、一貫性のある$タイプを続けるだろう。"

私は不思議なものと一致しますか?

http://json.codeplex.com/workitem/21989

私はむしろないだろう - 私はこれが私にはあまりにも固有のものであり、私は の設定で船外に行きたくないと思います。ある時点で私はおそらく を実装しています - http://json.codeplex.com/workitem/21856 - 人がJSONのメタプロパティを読み書きできるようにして、 は新しいプロパティ名でタイプ名の処理を再実装することができます。 他のオプションは、自分自身のソースコードを変更して、そのプロパティ名が になるようにするだけです。

これは私がカスタムJsonReaderを作成したように、我々は、このための必要性を持っていた...

json.Replace("\"$type\": \"", "\"type\": \""); 
+0

あなたのソリューションは最高です!^_^ –

+0

も参照してください:https://github.com/JamesNK/Newtonsoft.Json/issues/1331 – manuc66

3

私の解決策です。私たちは、複雑なデータモデルを持つMSのWebサービスでは安静を使用しており、 "__type"プロパティを "$ type"に置き換える必要がありました。

class MSJsonReader : JsonTextReader 
{ 
    public MSJsonTextReader(TextReader reader) : base(reader) { } 

    public override bool Read() 
    { 
     var hasToken = base.Read(); 

     if (hasToken && base.TokenType == JsonToken.PropertyName && base.Value != null && base.Value.Equals("__type")) 
      base.SetToken(JsonToken.PropertyName, "$type"); 

     return hasToken; 
    } 
} 

ここではどのように使用しますか。ここで

using(JsonReader jr = new MSJsonTextReader(sr)) 
{ 
    JsonSerializer s = new JsonSerializer(); 
    s.DateFormatHandling = DateFormatHandling.MicrosoftDateFormat; 
    s.NullValueHandling = NullValueHandling.Ignore; 
    s.TypeNameHandling = TypeNameHandling.Auto; // Important! 
    s.Binder = new MSRestToJsonDotNetSerializationBinder("Server.DataModelsNamespace", "Client.GeneratedModelsNamespace"); 

    T deserialized = s.Deserialize<T>(jr); 

    return deserialized; 
} 

はMS休息とJson.Net間の互換性を完了し、当社のMSRestToJsonDotNetSerializationBinderです。

class MSRestToJsonDotNetSerializationBinder : System.Runtime.Serialization.SerializationBinder 
{ 
    public string ServiceNamespace { get; set; } 
    public string LocalNamespace { get; set; } 

    public MSRestToJsonDotNetSerializationBinder(string serviceNamespace, string localNamespace) 
    { 
     if (serviceNamespace.EndsWith(".")) 
      serviceNamespace = serviceNamespace.Substring(0, -1); 

     if(localNamespace.EndsWith(".")) 
      localNamespace = localNamespace.Substring(0, -1); 

     ServiceNamespace = serviceNamespace; 
     LocalNamespace = localNamespace; 
    } 

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName) 
    { 
     assemblyName = null; 
     typeName = string.Format("{0}:#{1}", serializedType.Name, ServiceNamespace); // MS format 
    } 

    public override Type BindToType(string assemblyName, string typeName) 
    { 
     string jsonDotNetType = string.Format("{0}.{1}", LocalNamespace, typeName.Substring(0, typeName.IndexOf(":#"))); 
     return Type.GetType(jsonDotNetType); 
    } 
} 
1

カスタムタイプのプロパティ名をJson.NETにシリアル化できる別のオプションがあります。アイデアはデフォルトの$typeプロパティを書きませんが、クラス自体のプロパティとして型名を導入します。

我々はLocationクラスがあるとします、我々はtypeプロパティ名を導入し、以下に示すように、クラスを変更する

public class Location 
{ 
    public double Latitude { get; set; } 

    public double Longitude { get; set; } 
} 

まず必要があります。

public class Location 
{ 
    [JsonProperty("__type")] 
    public string EntityTypeName 
    { 

     get 
     { 
      var typeName = string.Format("{0}, {1}", GetType().FullName, GetType().Namespace); 
      return typeName; 
     } 
    } 

    public double Latitude { get; set; } 

    public double Longitude { get; set; } 
} 

その後、TypeNameHandling.NoneJsonSerializerSettings.TypeNameHandlingを設定デフォルトで$type属性のレンダリングをスキップするためにデシリアライザを使用します。

これだけです。

var point = new Location() { Latitude = 51.5033630, Longitude = -0.1276250 }; 

var jsonLocation = JsonConvert.SerializeObject(point, new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.None, //do not write type property(!) 
}); 
Console.WriteLine(jsonLocation); 

結果

{"__type":"Namespace.Location, Namespace","Latitude":51.503363,"Longitude":-0.127625} 
+0

デシリアライズがソリューションで正しいタイプを決定する方法はわかりません。説明できますか? –

+0

デシリアライズするには、 'JsonCreationConverter'を試してください。 http://stackoverflow.com/questions/8030538を参照してください。 – xmedeko

2

シリアライズするとき、プロパティ名オーバーライドする良い方法があります:

public class CustomJsonWriter : JsonTextWriter 
{ 
    public CustomJsonWriter(TextWriter writer) : base(writer) 
    { 
    } 

    public override void WritePropertyName(string name, bool escape) 
    { 
     if (name == "$type") name = "__type"; 
     base.WritePropertyName(name, escape); 
    } 
} 

var serializer = new JsonSerializer(); 
var writer = new StreamWriter(stream) { AutoFlush = true }; 
serializer.Serialize(new CustomJsonWriter(writer), objectToSerialize); 

私は試していないが、デシリアライゼーションはまだ、しかし、最悪の場合には私が使用することもできます

json.Replace("\"__type": \"", "\"type\": \"$type\"); 
2

Angular.js disregardsフィールド名は、ドル記号($)で始まるように私は私のUIのREST APIのためにこれをしなければなりませんでした。

そこでここでは、全体のWeb APIの__type$typeの名前を変更し、両方のシリアライズデシリアライゼーションのために機能するソリューションです。の

internal class CustomJsonNetFormatter : JsonMediaTypeFormatter 
{ 
    public override JsonReader CreateJsonReader(Type type, Stream readStream, Encoding effectiveEncoding) 
    { 
     return new CustomJsonReader(readStream, effectiveEncoding); 
    } 

    public override JsonWriter CreateJsonWriter(Type type, Stream writeStream, Encoding effectiveEncoding) 
    { 
     return new CustomJsonWriter(writeStream, effectiveEncoding); 
    } 

    private class CustomJsonWriter : JsonTextWriter 
    { 
     public CustomJsonWriter(Stream writeStream, Encoding effectiveEncoding) 
      : base(new StreamWriter(writeStream, effectiveEncoding)) 
     { 
     } 

     public override void WritePropertyName(string name, bool escape) 
     { 
      if (name == "$type") name = "__type"; 
      base.WritePropertyName(name, escape); 
     } 
    } 

    private class CustomJsonReader : JsonTextReader 
    { 
     public CustomJsonReader(Stream readStream, Encoding effectiveEncoding) 
      : base(new StreamReader(readStream, effectiveEncoding)) 
     { 
     } 

     public override bool Read() 
     { 
      var hasToken = base.Read(); 
      if (hasToken && TokenType == JsonToken.PropertyName && Value != null && Value.Equals("__type")) 
      { 
       SetToken(JsonToken.PropertyName, "$type"); 
      } 
      return hasToken; 
     } 
    } 
} 

カスタムJsonWriterとカスタムJsonReaderを(この質問に対する他の回答で提案されている)を使用できるようにするために、我々はJsonMediaTypeFormatterを継承し、対応するメソッドをオーバーライドする必要がありますもちろん、WebApiConfigにカスタムフォーマッタを登録する必要があります。そこで、デフォルトのJson.NETフォーマッタをカスタムのものに置き換えます。

config.Formatters.Remove(config.Formatters.JsonFormatter); 
config.Formatters.Add(new CustomJsonNetFormatter()); 

完了しました。

0

また、このようにそれを行うことができます:

[JsonConverter(typeof(JsonSubtypes), "ClassName")] 
public class Annimal 
{ 
    public virtual string ClassName { get; } 
    public string Color { get; set; } 
} 

あなたはNewtonsoft.Jsonプロジェクトの一部ではありませんJsonSubtypes コンバータが必要になります。

関連する問題