Json.Netには、ダイナミックタイプのみのタイプ名処理をオフにするための特定の設定はありません。関連する動的プロパティを[JsonProperty(TypeNameHandling = TypeNameHandling.None)]
とすることができない(またはしたくない)場合は、カスタム契約レゾルバを実装してプログラム的に動作を適用する唯一のオプション(Json.Netソースコード自体を変更すること) 。しかし、DefaultContractResolver
またはCamelCasePropertyNamesContractResolver
のようなJson.Net提供のリゾルバの1つからリゾルバを引き出すなら、これは難しくありません。ここで
はあなたが必要となるすべてのコードです:
using System;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
public class OmitTypeNamesOnDynamicsResolver : DefaultContractResolver
{
public static readonly OmitTypeNamesOnDynamicsResolver Instance = new OmitTypeNamesOnDynamicsResolver();
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty prop = base.CreateProperty(member, memberSerialization);
if (member.GetCustomAttribute<System.Runtime.CompilerServices.DynamicAttribute>() != null)
{
prop.TypeNameHandling = TypeNameHandling.None;
}
return prop;
}
}
すると、ちょうどJsonSerializerSettings
にリゾルバを追加し、すべて設定する必要があります。ここで
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
ContractResolver = OmitTypeNamesOnDynamicsResolver.Instance
};
string json = JsonConvert.SerializeObject(foo, settings);
は、コンセプトを証明するために、往復のデモです:
public class Program
{
public static void Main(string[] args)
{
Foo foo = new Foo
{
Model = new { link = "http://www.google.com", name = "John" },
Widget1 = new Doodad { Name = "Sprocket", Size = 10 },
Widget2 = new Thingy { Name = "Coil", Strength = 5 }
};
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
ContractResolver = OmitTypeNamesOnDynamicsResolver.Instance,
Formatting = Formatting.Indented
};
string json = JsonConvert.SerializeObject(foo, settings);
Console.WriteLine(json);
Console.WriteLine();
Foo foo2 = JsonConvert.DeserializeObject<Foo>(json, settings);
Console.WriteLine(foo2.Model.link);
Console.WriteLine(foo2.Model.name);
Console.WriteLine(foo2.Widget1.Name + " (" + foo2.Widget1.GetType().Name + ")");
Console.WriteLine(foo2.Widget2.Name + " (" + foo2.Widget2.GetType().Name + ")");
}
}
public class Foo
{
public dynamic Model { get; set; }
public AbstractWidget Widget1 { get; set; }
public AbstractWidget Widget2 { get; set; }
}
public class AbstractWidget
{
public string Name { get; set; }
}
public class Thingy : AbstractWidget
{
public int Strength { get; set; }
}
public class Doodad : AbstractWidget
{
public int Size { get; set; }
}
出力:
{
"Model": {
"link": "http://www.google.com",
"name": "John"
},
"Widget1": {
"$type": "Doodad, JsonTest",
"Size": 10,
"Name": "Sprocket"
},
"Widget2": {
"$type": "Thingy, JsonTest",
"Strength": 5,
"Name": "Coil"
}
}
http://www.google.com
John
Sprocket (Doodad)
Coil (Thingy)
[JsonIgnore]または条件付き直列化(http://www.newtonsoft.com /json/help/html/conditionalproperties.htm)は役に立つかもしれません。 – Nair
@Nair:ありがたいですが、残念です。私はドメインオブジェクトを所有していないので、属性やメソッドで飾ることはできません。それに、私はすべてのオブジェクトのためにこれをする必要があるので、それはうまくスケールされません。 – pardahlman
関連するプロパティに '[JsonProperty(TypeNameHandling = TypeNameHandling.None)]'を追加するのが最も簡単な方法ですが、あなたのコメントではできません。その要件を明確にするために質問を編集したいかもしれません。 – dbc