CSharp · Console
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Collections.ObjectModel;
using System.Reflection;
using System.ComponentModel;
using System.Globalization;
using System.Web.Routing;
using System.Net.Mail;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Net;
using System.Numerics;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
// // https://stackoverflow.com/questions/41945353/newtonsoft-jsonconvert-complex-number-issue
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);
}
}
public class Calculation
{
public Electrical Electrical { get; set; }
}
public class Electrical
{
public Impedance Impedance { get; set; }
}
public class Impedance
{
public Complex Z0 { get; set; }
public Complex Z1 { get; set; }
}
public class TestClass
{
public static void Test()
{
{
Console.WriteLine("Testing ComplexArrayConverter...");
var settings = new JsonSerializerSettings
{
Converters = { new ComplexArrayConverter() },
};
Test(settings);
Console.WriteLine("");
}
{
Console.WriteLine("Testing ComplexMathJSConverter...");
var settings = new JsonSerializerSettings
{
Converters = { new ComplexMathJSConverter() },
};
Test(settings);
Console.WriteLine("");
}
{
Console.WriteLine("Testing ComplexObjectConverter...");
var settings = new JsonSerializerSettings
{
Converters = { new ComplexObjectConverter() },
};
Test(settings);
Console.WriteLine("");
}
{
Console.WriteLine("Testing ComplexObjectConverter with CamelCasePropertyNamesContractResolver...");
var settings = new JsonSerializerSettings
{
Converters = { new ComplexObjectConverter() },
ContractResolver = new CamelCasePropertyNamesContractResolver(),
};
Test(settings);
Console.WriteLine("");
}
}
public static void Test(JsonSerializerSettings settings)
{
var calculation = new Calculation
{
Electrical = new Electrical
{
Impedance = new Impedance
{
Z0 = new Complex(0.0017923713150000001, 0),
Z1 = new Complex(3, 4),
}
}
};
var json = JsonConvert.SerializeObject(calculation, settings);
Console.WriteLine("Serialized JSON: ");
Console.WriteLine(json);
var calculation2 = JsonConvert.DeserializeObject<Calculation>(json, settings);
var json2 = JsonConvert.SerializeObject(calculation, settings);
Console.WriteLine("Deserialized and reserialized JSON: ");
Console.WriteLine(json2);
Assert.IsTrue(calculation.Electrical.Impedance.Z0 == calculation.Electrical.Impedance.Z0);
Assert.IsTrue(calculation.Electrical.Impedance.Z1 == calculation.Electrical.Impedance.Z1);
Console.WriteLine("Z0 and Z1 were serialized and deserialized successfully.");
}
}
public class AssertionFailedException : System.Exception
{
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
}
public static class Assert
{
public static void IsTrue(bool value)
{
if (value == false)
throw new AssertionFailedException("failed");
}
}
public class Program
{
public static void Main()
{
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("");
TestClass.Test();
}
}