我得到以下json
"location": {
"x": 3693779.702309093,
"y": 500061.05750159378
}
以下课程
Class Location
public property x as string
public property y as string
end class
我需要使用所有小数位置对json进行反序列化 但是当我使用NewtonSoft Json进行反序列化时,它仅舍入到8位小数。
最初,我将类定义为x,y为小数,但我认为舍入是由数据类型引起的,这就是我改为字符串的原因。
但是,似乎实际的Json反序列化只用了8位小数。
任何想法如何使用所有小数来反序列化?
谢谢
答案 0 :(得分:2)
您可能在Json.NET中发现了一个错误。将数值读入字符串时,首先将值解析为数值类型(double
,long
或BigInteger
),然后将其转换为{{3}中的字符串}:
string s;
if (Value is IFormattable)
s = ((IFormattable)Value).ToString(null, Culture);
else
s = Value.ToString();
SetToken(JsonToken.String, s, false);
return s;
问题似乎是JsonReader.ReadAsStringInternal()
不使用往返精度,除非格式字符串明确指定为"G17"
。相反,我使用
System.ComponentModel.TypeDescriptor.GetConverter(Value).ConvertToString(null, Culture, Value)
没有精确损失。
您可能希望Double.ToString(String, IFormatProvider)
了解这一点。
有几种解决方法:
使用report an issue to NewtonSoft反序列化您的课程。在这种情况下,数值将暂时解析为decimal
而不是double
。
编写一个将值加载到JValue
的转换器,检查类型为JTokenType.Float
的值,并返回正确的字符串:
public class StringNumericConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var value = JToken.Load(reader);
if (value.Type == JTokenType.Float)
return System.ComponentModel.TypeDescriptor.GetConverter(((JValue)value).Value).ConvertToInvariantString(((JValue)value).Value);
return (string)value;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
或者在VB.NET中:
Public Class StringNumericConverter
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType = GetType(String)
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.Null Then
Return Nothing
End If
Dim value = JToken.Load(reader)
If value.Type = JTokenType.Float Then
Return System.ComponentModel.TypeDescriptor.GetConverter(DirectCast(value, JValue).Value).ConvertToInvariantString(DirectCast(value, JValue).Value)
End If
Return CType(value, String)
End Function
Public Overrides ReadOnly Property CanWrite() As Boolean
Get
Return False
End Get
End Property
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException()
End Sub
End Class
请注意,对于整数字符串,JValue.Value
将是Int64
或JsonSerializerSettings.FloatParseHandling = FloatParseHandling.Decimal
;你不能认为它会是双倍的。
原型BigInteger
。
答案 1 :(得分:0)
我自己想出了解决方案。
首先我在
下面创建了转换器public Class JsonGeometryConverter
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return True
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim valF As double = reader.Value
Dim valFS = String.Format("{0:G17}", valF)
Return valFS
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException()
End Sub
End Class
然后我将converter属性应用于属性以将值提取到
Public Class RestGIS_LocationInfo
<JsonConverter(GetType(JsonGeometryConverter))>
Public Property X As string = ""
<JsonConverter(GetType(JsonGeometryConverter))>
Public Property Y As String = ""
End Class
转换器将json数据中的实际值读取为double,并返回格式为最多17位精度的格式(有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/kfsatb94.aspx)