JSONを逆シリアル化しようとしています:
{
"a":1,
"b":25,
"c":"1-7",
"obj1":{
"a1":10,
"b1":45,
"c1":60
},
"obj2":[
{
"a2":100,
"b2":15,
"c2":50
},
{
"e2":"1,2,5-7",
"f2":"1,3-5",
"a2":25
}
]
}
一部のフィールドに対してのみカスタム逆シリアル化を定義する方法を見つけたいと思います。
次のコードでは、注意が必要なフィールド(カスタム処理)と、何らかの方法で自動的に実行できるフィールドを分離しました。
「通常の」フィールドを自動的に逆シリアル化することは可能ですか? (特定のカスタム処理は必要ありません)
[JsonConverter(typeof(ConfigurationSerializer))]
public class Configuration
{
public int a { get; set; }
public int b { get; set; }
public Obj1 obj1 { get; set; }
public int[] c { get; set; }
public IList<Obj2> obj2 { get; set; }
}
public class ConfigurationSerializer : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jsonObject = JObject.Load(reader);
Configuration configuration = new Configuration();
// I would like this part to be automatic as I just repeat the default
// In the real case, I have many fields here!
configuration.a = (int)jsonObject["a"];
configuration.b = (int)jsonObject["b"];
configuration.obj1 = jsonObject["obj1"].ToObject<Obj1>();
// I created the JsonConverter for those 2 properties
configuration.c = myCustomProcessMethod(jsonObject["c"]);
configuration.obj2 = myCustomProcessMethod2(jsonObject["obj2"].ToObject<ValletConfiguration>());
return configuration;
}
public override bool CanConvert(Type objectType)
{
return typeof(Configuration).IsAssignableFrom(objectType);
}
}
とにかくJson.NET属性で型に注釈を付けているので、より簡単な解決策は、 [JsonConverter(Type)]
または [JsonProperty(ItemConverterType = Type)]
:
_public class Configuration
{
public int a { get; set; }
public int b { get; set; }
public Obj1 obj1 { get; set; }
// Converts the entire list to a compressed string
[JsonConverter(typeof(IntListConverter))]
public int[] c { get; set; }
// Converts each Obj2 item individually
[JsonProperty(ItemConverterType = typeof(Obj2Converter))]
public IList<Obj2> obj2 { get; set; }
}
_
それでも、コンバーターをConfiguration
に保持する必要がある場合(または実際にコンバーターを _JsonSerializerSettings.Converters
_ に追加していて、Json.NET属性をタイプに追加できない場合)は、次のことができます。 JObject
からカスタムプロパティを最初に削除する限り、 JsonSerializer.Populate()
を使用して標準プロパティを設定します。
_ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var jsonObject = JObject.Load(reader);
var configuration = (existingValue as Configuration ?? new Configuration());
// I created the JsonConverter for those 2 properties
configuration.c = myCustomProcessMethod(jsonObject["c"].RemoveFromLowestPossibleParent());
configuration.obj2 = myCustomProcessMethod2(jsonObject["obj2"].RemoveFromLowestPossibleParent().ToObject<ValletConfiguration>());
// Populate the remaining standard properties
using (var subReader = jsonObject.CreateReader())
{
serializer.Populate(subReader, configuration);
}
return configuration;
}
_
拡張メソッドの使用:
_public static class JsonExtensions
{
public static JToken RemoveFromLowestPossibleParent(this JToken node)
{
if (node == null)
return null;
var contained = node.AncestorsAndSelf().Where(t => t.Parent is JContainer && t.Parent.Type != JTokenType.Property).FirstOrDefault();
if (contained != null)
contained.Remove();
// Also detach the node from its immediate containing property -- Remove() does not do this even though it seems like it should
if (node.Parent is JProperty)
((JProperty)node.Parent).Value = null;
return node;
}
}
_
考えられる方法は、プロキシプロパティを作成して、正しくシリアル化および逆シリアル化することです。 ScriptIgnoreAttribute ( JsonIgnoreAttribute も可能です)を使用すると、実際のプロパティはシリアル化されません。次に例を示します。
[ScriptIgnore]
public int RealProperty { get; set; }
public string RealPropertyProxy
{
get
{
return SerializeRealProperty(RealProperty);
}
set
{
RealProperty = DeserializeRealProperty(value);
}
}
その結果、プロキシのみが(不動産の値に基づいて)定義した方法でシリアル化されます。特別な方法でシリアル化する必要があるプロパティを変更するだけで、特別なJsonConverter
を実装する必要はありません。