Newtonsoft JsonConvert 复数问题
Newtonsoft JsonConvert Complex Number Issue
我在相当复杂的 DTO 上使用 Newtonsoft JsonConvert.SerializeObject 和 JsonConvert.DeserializeObject。其中,我有一些复数 (System.Numerics)。除了复数,一切都完美无缺。
数字序列化良好,导致:
{
... lots of JSON here ...
"Electrical": {
... lots of JSON objects ...
"Z1": {
"Real": 0.0017923713150000001,
"Imaginary": 0.0,
"Magnitude": 0.0017923713150000001,
"Phase": 0.0
},
"Z0": {
"Real": 0.0017923713150000001,
"Imaginary": 0.0,
"Magnitude": 0.0017923713150000001,
"Phase": 0.0
}
}
... lots of JSON .. here ...
}
问题出在反序列化,其中返回的复数全是零,例如:
calculation.Electrical.Impedance.Z0
{(0, 0)}
Imaginary: 0
Magnitude: 0
Phase: 0
Real: 0
m_imaginary: 0
m_real: 0
任何有关如何解决此问题的建议都很好。
Json.NET 和从 JSON 到 JSON 序列化 Complex
的 JSON standard have a predefined format for complex numbers, and so Json.NET will serialize all the properties of a Complex
, generating the output you see. To get clean JSON with just the necessary data, you will need to write a custom JsonConverter
都不是。
但是,应该使用什么格式呢?选项可能包括:
- 作为数组:
[0.0017923713150000001,0.0]
.
- 作为具有
"Real"
和 "Imaginary"
属性的对象:{"Real":0.0017923713150000001,"Imaginary":0.0}
.
- 在math.js format中:
{"mathjs":"Complex","re":0.0017923713150000001,"im":0.0}
。
以下是每种格式的转换器:
public abstract class ComplexConverterBase : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Complex) || objectType == typeof(Complex?);
}
}
public class ComplexArrayConverter : ComplexConverterBase
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var array = serializer.Deserialize<double[]>(reader);
if (array.Length != 2)
{
throw new JsonSerializationException(string.Format("Invalid complex number array of length {0}", array.Length));
}
return new Complex(array[0], array[1]);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var complex = (Complex)value;
writer.WriteStartArray();
writer.WriteValue(complex.Real);
writer.WriteValue(complex.Imaginary);
writer.WriteEndArray();
}
}
public class ComplexObjectConverter : ComplexConverterBase
{
// By using a surrogate type, we respect the naming conventions of the serializer's contract resolver.
class ComplexSurrogate
{
public double Real { get; set; }
public double Imaginary { get; set; }
public static implicit operator Complex(ComplexSurrogate surrogate)
{
if (surrogate == null)
return default(Complex);
return new Complex(surrogate.Real, surrogate.Imaginary);
}
public static implicit operator ComplexSurrogate(Complex complex)
{
return new ComplexSurrogate { Real = complex.Real, Imaginary = complex.Imaginary };
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
return (Complex)serializer.Deserialize<ComplexSurrogate>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, (ComplexSurrogate)(Complex)value);
}
}
public class ComplexMathJSConverter : ComplexConverterBase
{
// Serialize in math.js format
// http://mathjs.org/docs/core/serialization.html
// By using a surrogate type, we respect the naming conventions of the serializer's contract resolver.
class ComplexSurrogate
{
[JsonProperty(Order = 1)]
public double re { get; set; }
[JsonProperty(Order = 2)]
public double im { get; set; }
[JsonProperty(Order = 0)]
public string mathjs { get { return "Complex"; } }
public static implicit operator Complex(ComplexSurrogate surrogate)
{
if (surrogate == null)
return default(Complex);
return new Complex(surrogate.re, surrogate.im);
}
public static implicit operator ComplexSurrogate(Complex complex)
{
return new ComplexSurrogate { re = complex.Real, im = complex.Imaginary };
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
return (Complex)serializer.Deserialize<ComplexSurrogate>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, (ComplexSurrogate)(Complex)value);
}
}
然后,您将序列化如下:
var settings = new JsonSerializerSettings
{
// Add a complex converter to the Converts array.
// Use one of ComplexArrayConverter, ComplexMathJSConverter and ComplexObjectConverter
Converters = { new ComplexArrayConverter() },
};
var json = JsonConvert.SerializeObject(calculation, settings);
要在全局设置中使用转换器,请参阅here for Web API or here 直接调用序列化程序时。
示例 fiddle.
我在相当复杂的 DTO 上使用 Newtonsoft JsonConvert.SerializeObject 和 JsonConvert.DeserializeObject。其中,我有一些复数 (System.Numerics)。除了复数,一切都完美无缺。
数字序列化良好,导致:
{
... lots of JSON here ...
"Electrical": {
... lots of JSON objects ...
"Z1": {
"Real": 0.0017923713150000001,
"Imaginary": 0.0,
"Magnitude": 0.0017923713150000001,
"Phase": 0.0
},
"Z0": {
"Real": 0.0017923713150000001,
"Imaginary": 0.0,
"Magnitude": 0.0017923713150000001,
"Phase": 0.0
}
}
... lots of JSON .. here ...
}
问题出在反序列化,其中返回的复数全是零,例如:
calculation.Electrical.Impedance.Z0
{(0, 0)}
Imaginary: 0
Magnitude: 0
Phase: 0
Real: 0
m_imaginary: 0
m_real: 0
任何有关如何解决此问题的建议都很好。
Json.NET 和从 JSON 到 JSON 序列化 Complex
的 JSON standard have a predefined format for complex numbers, and so Json.NET will serialize all the properties of a Complex
, generating the output you see. To get clean JSON with just the necessary data, you will need to write a custom JsonConverter
都不是。
但是,应该使用什么格式呢?选项可能包括:
- 作为数组:
[0.0017923713150000001,0.0]
. - 作为具有
"Real"
和"Imaginary"
属性的对象:{"Real":0.0017923713150000001,"Imaginary":0.0}
. - 在math.js format中:
{"mathjs":"Complex","re":0.0017923713150000001,"im":0.0}
。
以下是每种格式的转换器:
public abstract class ComplexConverterBase : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Complex) || objectType == typeof(Complex?);
}
}
public class ComplexArrayConverter : ComplexConverterBase
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var array = serializer.Deserialize<double[]>(reader);
if (array.Length != 2)
{
throw new JsonSerializationException(string.Format("Invalid complex number array of length {0}", array.Length));
}
return new Complex(array[0], array[1]);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var complex = (Complex)value;
writer.WriteStartArray();
writer.WriteValue(complex.Real);
writer.WriteValue(complex.Imaginary);
writer.WriteEndArray();
}
}
public class ComplexObjectConverter : ComplexConverterBase
{
// By using a surrogate type, we respect the naming conventions of the serializer's contract resolver.
class ComplexSurrogate
{
public double Real { get; set; }
public double Imaginary { get; set; }
public static implicit operator Complex(ComplexSurrogate surrogate)
{
if (surrogate == null)
return default(Complex);
return new Complex(surrogate.Real, surrogate.Imaginary);
}
public static implicit operator ComplexSurrogate(Complex complex)
{
return new ComplexSurrogate { Real = complex.Real, Imaginary = complex.Imaginary };
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
return (Complex)serializer.Deserialize<ComplexSurrogate>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, (ComplexSurrogate)(Complex)value);
}
}
public class ComplexMathJSConverter : ComplexConverterBase
{
// Serialize in math.js format
// http://mathjs.org/docs/core/serialization.html
// By using a surrogate type, we respect the naming conventions of the serializer's contract resolver.
class ComplexSurrogate
{
[JsonProperty(Order = 1)]
public double re { get; set; }
[JsonProperty(Order = 2)]
public double im { get; set; }
[JsonProperty(Order = 0)]
public string mathjs { get { return "Complex"; } }
public static implicit operator Complex(ComplexSurrogate surrogate)
{
if (surrogate == null)
return default(Complex);
return new Complex(surrogate.re, surrogate.im);
}
public static implicit operator ComplexSurrogate(Complex complex)
{
return new ComplexSurrogate { re = complex.Real, im = complex.Imaginary };
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
return (Complex)serializer.Deserialize<ComplexSurrogate>(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, (ComplexSurrogate)(Complex)value);
}
}
然后,您将序列化如下:
var settings = new JsonSerializerSettings
{
// Add a complex converter to the Converts array.
// Use one of ComplexArrayConverter, ComplexMathJSConverter and ComplexObjectConverter
Converters = { new ComplexArrayConverter() },
};
var json = JsonConvert.SerializeObject(calculation, settings);
要在全局设置中使用转换器,请参阅here for Web API or here 直接调用序列化程序时。
示例 fiddle.