11

ASP.NET MVC アプリケーションを Newtonsoft JsonSerializer を使用して JSON シリアル化を行うように切り替えました。

var writer = new JsonTextWriter(HttpContext.Response.Output) { Formatting = Formatting };
var serializer = JsonSerializer.Create();
serializer.Serialize(writer, myData);

これにより、 $id および $ref プロパティを持つ JSON が生成され、重複するオブジェクトが JSON から削除されます。これが優れた機能であることはわかっていますが、この JSON を読み取るクライアントは、これらの参照の解釈をサポートできず、完全なオブジェクトが存在することを期待できません。PreserveReferencesHandlingプロパティをすべての可能な値に設定しようとしましJsonSerializerSettingsたが、違いはないようです。

$id および $ref プロパティの作成を無効にして、Newtonsoft シリアライザーにオブジェクト グラフ全体を書き出すにはどうすればよいですか?

EDIT : これはサンプル C# クラス、私が期待する JSON、および Newtonsoft シリアライザーによって作成された JSON です。

public class Product
{
    public Image MainImage { get; set; }

    public List<Image> AllImages { get; set; }
}

public class Image
{
    public int Id { get; set; }
    public string Url { get; set; }
}

私が期待するJSON:

{
    MainImage: { Id: 1, Url: 'http://contoso.com/product.png' },
    AllImages: [{ Id: 1, Url: 'http://contoso.com/product.png' },{ Id: 2, Url: 'http://contoso.com/product2.png' }]
}

Newtonsoft シリアライザーによって作成された JSON (MainImage に追加された $id パラメーターと、参照されるオブジェクトが完全に $ref パラメーターに置き換えられていることに注意してください):

{
    MainImage: { $id: 1, Id: 1, Url: 'http://contoso.com/product.png' },
    AllImages: [{ $ref: 1 },{ Id: 2, Url: 'http://contoso.com/product2.png' }]
}

Newtonsoft バージョンの方が優れている (DRYer である) ことは理解していますが、この JSON 出力を読み取るクライアントは $ref の意味を理解していません。

4

1 に答える 1

24

あなたのコメントから、あなたのクラスは実際に で装飾されていることがわかり[DataContract(IsReference = true)]ます. Serialization Attributes に関する JSON.Net ドキュメントから:

組み込みの Json.NET 属性を使用するだけでなく、Json.NET は、JSON をシリアル化および逆シリアル化する方法を決定するときに、 SerializableAttribute (DefaultContractResolver の IgnoreSerializableAttribute が false に設定されている場合) DataContractAttributeDataMemberAttributeおよびNonSerializedAttribute ... も探します。

また、次のようにも述べています。

ノート

Json.NET 属性は、標準の .NET シリアル化属性よりも優先されます。たとえば、JsonPropertyAttribute と DataMemberAttribute の両方がプロパティに存在し、両方が名前をカスタマイズする場合、JsonPropertyAttribute の名前が使用されます。

したがって、問題の解決策は簡単な[JsonObject(IsReference = false)]ようです。次のようにクラスに追加するだけです。

[DataContract(IsReference = true)]
[JsonObject(IsReference = false)]
public class Product
{
    [DataMember]
    public Image MainImage { get; set; }
    [DataMember]
    public List<Image> AllImages { get; set; }
}

[DataContract(IsReference = true)]
[JsonObject(IsReference = false)]
public class Image
{
    [DataMember]
    public int Id { get; set; }
    [DataMember]
    public string Url { get; set; }
}

これにより、WCF 属性をそのまま維持できますが、JSON にシリアル化するときに参照動作がオーバーライドされます。

于 2013-10-11T20:25:01.537 に答える