Newtonsoft JsonConvert 复数问题
Posted
技术标签:
【中文标题】Newtonsoft JsonConvert 复数问题【英文标题】:Newtonsoft JsonConvert Complex Number Issue 【发布时间】:2017-01-30 21:02:19 【问题描述】:我在相当复杂的 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
任何有关如何解决此问题的建议都会很棒。
【问题讨论】:
您可能只需要实现一个自定义的JsonConverter
类。在此处查看答案以获取类似示例:***.com/questions/24051206/…
【参考方案1】:
Json.NET 和 JSON standard 都没有预定义的复数格式,因此 Json.NET 将序列化 Complex
的所有属性,生成您看到的输出。要获得只包含必要数据的干净 JSON,您需要编写一个 custom JsonConverter
将 Complex
从 JSON 序列化到 JSON。
但是,应该使用什么格式?选项可能包括:
-
作为数组:
[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 用于 Web API 或 here 直接调用序列化程序。
示例fiddle。
【讨论】:
dbc,感谢您清晰详细的解释。它工作得很好。经过数小时的搜索,您的回答对我们很有帮助。以上是关于Newtonsoft JsonConvert 复数问题的主要内容,如果未能解决你的问题,请参考以下文章
JsonConvert 在 Newtonsoft.Json Asp.net MVC C# 中不起作用
Newtonsoft.Json.JsonConvert 序列化与反序列化
找不到方法 Void Newtonsoft.Json.JsonConvert.set_DefaultSettings