4

Newtonsoft Json.NET カスタムJsonConverterWriteJsonメソッドで、デフォルトのオブジェクトのシリアル化動作を 内からアピールできますJsonConverterか?

つまり、カスタム コンバーターが登録されていなかった場合に発生するシリアライゼーションを延期できますか?

詳細

与えられた価格クラス

public class Price
{
    public string CurrencyCode;
    public decimal Amount;
}

通常の Newtonsoft Json.NET の動作はPrice、参照が null の場合にのみ、インスタンスを null としてシリアル化することです。Priceさらに、ゼロになるたびにインスタンスを null としてシリアライズしたいと考えていPrice.Amountます。これが私がこれまでに取り組んできたことです(完全なソースコード

public class PriceConverter : JsonConverter 
{
    // ...

    public override void WriteJson(
        JsonWriter writer, 
        object value, 
        JsonSerializer serializer) 
    {
        var price = (Price)value;

        if (0 == price.Amount) {
            writer.WriteNull();
            return;
        }

        // I'd like to replace the rest of this method with an appeal to the 
        // default serialization behavior.
        writer.WriteStartObject();
        writer.WritePropertyName("amount");
        writer.WriteValue(price.Amount);
        writer.WritePropertyName("currencyCode");
        writer.WriteValue(price.CurrencyCode);
        writer.WriteEndObject();
    }

    // ...
}

この実装の最後の部分は脆弱です。たとえば、 にフィールドを追加するPriceと、シリアライゼーションが壊れてしまいます (そして、壊れたことを検出するテストを作成する良い方法がわかりません)。

私のシリアライザーには、保持する必要があるJsonSerializerSettingsを介して別のアセンブリで構成された多くの動作があります(キャメルケースのプロパティ名など)。これら 2 つの間に直接的な依存関係を追加することはできません。実際には、[JsonConverter(typeof(PriceConverter))]属性を使用して、カスタム コンバーターを に使用する必要があることを指定していますPrice

4

2 に答える 2

2

コンバーターが設定を受信できるようにするための回避策があります。シリアライゼーション コンテキストを使用できます。

設定:

var settings = new JsonSerializerSettings { /*...*/ };
settings.Context = new StreamingContext(StreamingContextStates.All, settings);

コンバーターで:

var settings = (JsonSerializerSettings)serializer.Context.Context;

やると汚れますけどね。

于 2013-06-07T06:05:44.347 に答える
0

このアプローチの何が問題なのですか?

public static JsonSerializerSettings MySettings()
{
    return new JsonSerializerSettings
        {
        ContractResolver = new CamelCasePropertyNamesContractResolver(),
        TypeNameHandling = TypeNameHandling.All,
        DefaultValueHandling = DefaultValueHandling.Ignore,
        DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind,
        };
}

あなたのPriceConverter

if (0 == price.Amount)
{
    writer.WriteNull();
    return;
}
else
{
    writer.WriteRaw(JsonConvert.SerializeObject(value, Somewhere.MySettings()));
    return;
}

そしてあなたのプログラムでは:

    public static void Custom(Price p)
    {
        var settings = Somewhere.MySettings();
        settings.Converters = new List<JsonConverter> { new PriceConverter() };

        Console.WriteLine("custom: " +
            JsonConvert.SerializeObject(p, settings));
    }
于 2013-06-05T20:23:26.353 に答える