如何使用 Json.NET 在 C# 中序列化"union-like"字段



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

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

如何在c#中使用Json来处理这种情况?净序列化器吗?

可能的解决方案将涉及两个带有自定义setter的属性,当其中一个属性与某种自定义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 }

我刚刚遇到了一个类似的问题。对于合约的简单操作,请查看:在Json中重写序列化行为。净

要解析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)
         {
            //....
         }
      }      
   }

如何确定要从读者中反序列化的类型是你的作业;)

最新更新