【问题标题】:How to serialize a "union-like" field in C# with Json.NET如何使用 Json.NET 在 C# 中序列化“类似联合”的字段
【发布时间】:2011-11-14 16:57:21
【问题描述】:

我正在尝试生成将在 Dojo javascript 框架中使用的 JSON 文件,并希望返回 position 属性以在 dojo.place() 调用中使用。 position 参数可以是要么 数字或字符串。

使用 StructLayout 似乎无法按原样工作,因为序列化程序会尝试同时发出 String 和 Integer 类型。我正在考虑创建一个自定义ContractResolver,它覆盖CreatePrimitiveContract 以返回一个自定义JsonConverter 类。但是,查看 API,JsonConverter 似乎是基于类型创建的,而不是特定的对象值。

如何使用 Json.NET 序列化程序在 C# 中处理这种情况?

据推测,解决方案将涉及两个带有自定义设置器的属性,以在将一个属性与某种自定义 Json.Net 类一起设置以检查属性值并仅序列化非空属性时,将另一个属性设为空。

** 假设示例 **

// C# struct (or class)
[StructLayout(LayoutKind.Explicit)]
struct DojoPosition {
   [JsonProperty(PropertyName="position")]
   [FieldOffset(0)]
   public String StrPos;

   [JsonProperty(PropertyName="position")]
   [FieldOffset(0)]
   public Int32 IntPos;
}

// Serialization output
DojoPosition pos;
pos.StrPos = "only";
var output = JsonConvert.SerializeObject(pos);

// Output is: { "position": "only" }

pos.IntPos = 3;
var output = JsonConvert.SerializeObject(pos);

// Output is: { "position": 3 }

【问题讨论】:

    标签: serialization c#-4.0 dojo json.net unions


    【解决方案1】:

    我刚刚遇到了类似的问题。 对于合约的简单操作,请查看:Overriding the serialization behaviour in Json.Net

    为了解决 JsonPrimitiveContract 覆盖 CreateContract 方法。

    以下是基于我们的解决方案的示例:

       public class JsonDotNetContractResolver : DefaultContractResolver
       {
          protected override JsonContract CreateContract(Type objectType)
          {
             if (typeof(DojoPosition).IsAssignableFrom(objectType))
             {
                return new JsonPrimitiveContract(objectType.GetGenericArguments()[1])
                          {
                             CreatedType = typeof(object), // Not sure this will work for you, or is necessary...
                             IsReference = false,
                             Converter = DojoPositionConverter,
                          };
             }
             return base.CreateContract(objectType);
          }
          private class DojoPositionConverter : JsonConverter
          {
             public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
             {
                var dp = (DojoPosition) value;
                if(string.IsNullOrEmpty(dp.StrPos))
                   serializer.Serialize(writer,dp.IntPos);
                else
                   serializer.Serialize(writer,dp.StrPos);
             }
             public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
             {
                //...
             }
             public override bool CanConvert(Type objectType)
             {
                //....
             }
          }      
       }
    

    如何从阅读器中确定要反序列化的类型是你的功课;)

    【讨论】:

    • 完美!我错过了通过CreateContract 方法的连接。这让我走上了正轨。
    猜你喜欢
    • 1970-01-01
    • 2019-02-07
    • 2011-03-20
    • 2019-01-29
    • 1970-01-01
    • 2015-12-10
    • 2018-04-25
    • 1970-01-01
    • 2012-05-08
    相关资源
    最近更新 更多