我正在尝试生成一个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)
{
//....
}
}
}
如何确定要从读者中反序列化的类型是你的作业;)