我定义了以下类:
<TypeConverter(GetType(ExpandableObjectConverter))>
<DataContract()>
Public Class Vector3
<DataMember()> Public Property X As Double
<DataMember()> Public Property Y As Double
<DataMember()> Public Property Z As Double
Public Overrides Function ToString() As String
Return String.Format("({0}, {1}, {2})",
Format(X, "0.00"),
Format(Y, "0.00"),
Format(Z, "0.00"))
End Function
End Class
使用DataContractJsonSerializer
我按预期收到以下JSON:
{
"Vector": {
"X": 1.23,
"Y": 4.56,
"Z": 7.89
}
}
然而,JSON.NET产生:
{
"Vector": "(1.23, 4.56, 7.89)"
}
如果我从类中删除ExpandableObjectConverter
属性,JSON.NET会按预期生成结果(与DataContractJsonSerializer相同)。
不幸的是,我需要ExpandableObjectConverter
,以便该类可以使用属性网格。
有没有办法告诉JSON.NET忽略ExpandableObjectConverters
?
我更喜欢使用JSON.NET而不是DataContractJsonSerializer
,因为将枚举序列化为字符串表示要容易得多。
答案 0 :(得分:6)
虽然我很欣赏Rivers的回答,但我真的在寻找一种自动忽略所有可扩展对象转换器的解决方案(比如DataContractJsonSerializer),而不是为每个违规类构建一个自定义JsonConverter。
我找到了以下两种解决方案:
由于默认的ExpandableObjectConverter支持转换为/来自字符串,因此JSON.NET使用字符串序列化该类。为了抵消这种情况,我创建了自己的可扩展对象转换器,它不允许转换为/来自字符串。
Imports System.ComponentModel
Public Class SerializableExpandableObjectConverter
Inherits ExpandableObjectConverter
Public Overrides Function CanConvertTo(context As System.ComponentModel.ITypeDescriptorContext, destinationType As System.Type) As Boolean
If destinationType Is GetType(String) Then
Return False
Else
Return MyBase.CanConvertTo(context, destinationType)
End If
End Function
Public Overrides Function CanConvertFrom(context As System.ComponentModel.ITypeDescriptorContext, sourceType As System.Type) As Boolean
If sourceType Is GetType(String) Then
Return False
Else
Return MyBase.CanConvertFrom(context, sourceType)
End If
End Function
End Class
应用上面的转换器可以完美地使用JSON.NET和属性网格控件!
答案 1 :(得分:1)
由于您正在指定TypeConverter,Json.net使用它。要解决这个问题,请使用LINQ to Json创建一个JsonConverter以使用您需要的格式:
Public Class Vector3Converter
Inherits JsonConverter
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Dim vector = DirectCast(value, Vector3)
serializer.Serialize(writer, New JObject() From { _
{"X", vector.X}, _
{"Y", vector.Y}, _
{"Z", vector.Z} _
})
End Sub
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim jObject = serializer.Deserialize(Of JObject)(reader)
Return New Vector3() With { _
Key .X = CDbl(jObject("X")), _
Key .Y = CDbl(jObject("Y")), _
Key .Z = CDbl(jObject("Z")) _
}
End Function
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType = GetType(Vector3)
End Function
End Class
然后,将其分配给您的类型:
<TypeConverter(GetType(System.ComponentModel.ExpandableObjectConverter))> _
<DataContract> _
<JsonConverter(GetType(Vector3Converter))> _
Public Class Vector3
End Class
我最初使用C#并使用在线转换器到VB,所以它可能有点偏。
答案 2 :(得分:0)
感谢 JRS 发布此信息。 C# 的用户可以使用来自 VB 的这个翻译:
public class SerializableExpandableObjectConverter : ExpandableObjectConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if(destinationType == typeof(string))
{
return false;
}
else
{
return base.CanConvertTo(context, destinationType);
}
}
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if(sourceType == typeof(string))
{
return false;
}
else
{
return base.CanConvertFrom(context, sourceType);
}
}
}