2

メンバーが装飾されている多くのデータ コントラクトを持つシステムがあります。

[DataMember(EmitDefaultValue = false)]  

JSON にシリアル化するときに null のときにメンバーを含める必要がある場合があります。どのようなシリアライザー設定を選択しても、これを機能させることはできません。

   [TestMethod]
    public void SerializationTest()
    {

        var contract = Activator.CreateInstance(typeof(TestContract));

        var formatter = new JsonMediaTypeFormatter
        {
            SerializerSettings = new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Include,
                DefaultValueHandling = DefaultValueHandling.Ignore,
                TypeNameHandling = TypeNameHandling.All,
                ContractResolver = new DataContractResolver(),
                Binder = new DataContractBinder()
            }
        };

        var result = JsonConvert.SerializeObject(contract, formatter.SerializerSettings);
    }

プロパティごとに追加のオーバーライドを提供するカスタム データ コントラクト リゾルバーも作成しました。

        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {                        
        var property = base.CreateProperty(member, MemberSerialization.Fields);                        
        property.NullValueHandling = NullValueHandling.Include;            
        property.DefaultValueHandling = DefaultValueHandling.Ignore;
        property.ShouldSerialize = o => true;
        return property;
    }

エミットのデフォルト値 = false を無視するために、null 値の処理とデフォルト値の処理のすべてのバリエーションを試しました。json net docs によると、これらの設定により、オブジェクトの null プロパティが得られるはずです。json ネット ソースをデバッグする前に、他に不足しているものはありますか?

4

1 に答える 1

7

コントラクト リゾルバーではproperty.DefaultValueHandling = DefaultValueHandling.Includeなく設定する必要があります。DefaultValueHandling.Ignore

public class DataContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        property.NullValueHandling = NullValueHandling.Include;
        property.DefaultValueHandling = DefaultValueHandling.Include;
        property.ShouldSerialize = o => true;
        return property;
    }
}

Json.NET は、メンバーをシリアル化する前に と の両方をチェックします。メンバーをシリアル化するには、DefaultValueHandling両方チェックに合格する必要があります。そして、お気づきのように、いずれかがコントラクトのプロパティで明示的に設定されている場合、それは の設定をオーバーライドします。これは、カスタム コントラクト リゾルバーが必要な理由を説明しています。NullValueHandlingJsonSerializerSettings

最高のパフォーマンスを得るために、コントラクト リゾルバーをキャッシュすることをお勧めします。

于 2016-08-15T19:07:39.113 に答える