JSON に余分な簿記情報が含まれていることを気にしない場合は、@Athari が提案したように、PreserveReferenceHandling
オプションJsonSerializerSettings
をAll
(または) に設定します。Objects
それが最も簡単な方法です。これを行うと、JSON は次のようになります。
{
"$id": "1",
"Id": 123,
"OtherStuff": "other stuff A",
"MyChild": {
"$id": "2",
"Id": 456,
"OtherStuff": "other stuff B",
"MyParent": {
"$ref": "1"
}
}
}
そうは言っても、 custom を使用して、元々望んでいたことを行う方法がありますJsonConverter
。できることは、Id プロパティを持つ任意のオブジェクトを受け入れるコンバーターを作成することです。次に、ID としてのみシリアル化する必要がある場所では、それらのプロパティを[JsonConverter]
属性で装飾できます。カスタム コンバーターはそのような場合に使用されますが、それ以外の場合には使用されません。コンバーターは次のようになります。
class IdOnlyConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType.IsClass;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName("Id");
writer.WriteValue(GetId(value));
writer.WriteEndObject();
}
private int GetId(object obj)
{
PropertyInfo prop = obj.GetType().GetProperty("Id", typeof(int));
if (prop != null && prop.CanRead)
{
return (int)prop.GetValue(obj, null);
}
return 0;
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
コンバーターを使用するには、概説したようにクラスを設定します。Json.NetMyParent
にそのプロパティのカスタム コンバーターを使用するように指示する属性で装飾されていることに注目してください。
public class ObjA
{
public int Id { get; set; }
public string OtherStuff { get; set; }
public ObjB MyChild { get; set; }
}
public class ObjB
{
public int Id { get; set; }
public string OtherStuff { get; set; }
[JsonConverter(typeof(IdOnlyConverter))]
public ObjA MyParent { get; set; }
}
シリアル化するときは、toのReferenceLoopHandling
オプションを設定して、参照ループが検出された場合にエラーをスローしないように Json.Net に指示し、とにかくシリアル化を続行する必要があります (コンバーターがそれを処理するため)。JsonSerializerSettings
Serialize
すべてをまとめると、コンバーターの動作を示すコード例がいくつかあります。
class Program
{
static void Main(string[] args)
{
ObjA a = new ObjA();
a.Id = 123;
a.OtherStuff = "other stuff A";
ObjB b = new ObjB();
b.Id = 456;
b.OtherStuff = "other stuff B";
b.MyParent = a;
a.MyChild = b;
JsonSerializerSettings settings = new JsonSerializerSettings
{
ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize,
Formatting = Newtonsoft.Json.Formatting.Indented
};
string json = JsonConvert.SerializeObject(a, settings);
Console.WriteLine(json);
}
}
そして、これが上記の出力です:
{
"Id": 123,
"OtherStuff": "other stuff A",
"MyChild": {
"Id": 456,
"OtherStuff": "other stuff B",
"MyParent": {
"Id": 123
}
}
}