using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Collections.ObjectModel;
using System.Text.Json.Serialization;
public class ObjectAsPrimitiveConverter : JsonConverter<object>
FloatFormat FloatFormat { get; init; }
UnknownNumberFormat UnknownNumberFormat { get; init; }
ObjectFormat ObjectFormat { get; init; }
public ObjectAsPrimitiveConverter() : this(FloatFormat.Double, UnknownNumberFormat.Error, ObjectFormat.Expando) { }
public ObjectAsPrimitiveConverter(FloatFormat floatFormat, UnknownNumberFormat unknownNumberFormat, ObjectFormat objectFormat)
this.FloatFormat = floatFormat;
this.UnknownNumberFormat = unknownNumberFormat;
this.ObjectFormat = objectFormat;
public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
if (value.GetType() == typeof(object))
writer.WriteStartObject();
JsonSerializer.Serialize(writer, value, value.GetType(), options);
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
switch (reader.TokenType)
case JsonTokenType.False:
case JsonTokenType.String:
return reader.GetString();
case JsonTokenType.Number:
if (reader.TryGetInt32(out var i))
if (reader.TryGetInt64(out var l))
if (FloatFormat == FloatFormat.Decimal && reader.TryGetDecimal(out var m))
else if (FloatFormat == FloatFormat.Double && reader.TryGetDouble(out var d))
using var doc = JsonDocument.ParseValue(ref reader);
if (UnknownNumberFormat == UnknownNumberFormat.JsonElement)
return doc.RootElement.Clone();
throw new JsonException(string.Format("Cannot parse number {0}", doc.RootElement.ToString()));
case JsonTokenType.StartArray:
var list = new List<object>();
switch (reader.TokenType)
list.Add(Read(ref reader, typeof(object), options));
case JsonTokenType.EndArray:
throw new JsonException();
case JsonTokenType.StartObject:
var dict = CreateDictionary();
switch (reader.TokenType)
case JsonTokenType.EndObject:
case JsonTokenType.PropertyName:
var key = reader.GetString();
dict.Add(key, Read(ref reader, typeof(object), options));
throw new JsonException();
throw new JsonException();
throw new JsonException(string.Format("Unknown token {0}", reader.TokenType));
protected virtual IDictionary<string, object> CreateDictionary() =>
ObjectFormat == ObjectFormat.Expando ? new ExpandoObject() : new Dictionary<string, object>();
public enum UnknownNumberFormat
public static void Test()
var options = new JsonSerializerOptions
Converters = { new ObjectAsPrimitiveConverter(floatFormat : FloatFormat.Double, unknownNumberFormat : UnknownNumberFormat.Error, objectFormat : ObjectFormat.Expando) },
dynamic d = JsonSerializer.Deserialize<dynamic>(json, options);
Assert.AreEqual(true, d.boolean);
Assert.AreEqual("string", d.String);
Assert.AreEqual(null, d.Null);
Assert.AreEqual(3.14, d.Double);
Assert.AreEqual(100101, d.Int);
Assert.AreEqual(9223372036854775800L, d.Long);
Assert.IsTrue((new object [] { "a", "b", "c" }).SequenceEqual((IEnumerable<object>)d.ArrayOfStrings));
var reserialized = JsonSerializer.Serialize(d, options);
var element = JsonSerializer.Deserialize<JsonElement>(json);
var elementJson = JsonSerializer.Serialize(element, new JsonSerializerOptions { WriteIndented = true });
Assert.AreEqual(elementJson, reserialized);
Assert.AreEqual("{}", JsonSerializer.Serialize(new object(), options));
Console.WriteLine("Re-serialized JSON:");
Console.WriteLine(reserialized);
static string GetJson() =>
""Long"": 9223372036854775800,
""ArrayOfStrings"":[""a"",""b"",""c""],
""servlet-name"": ""cofaxCDS"",
""servlet-class"": ""org.cofax.cds.CDSServlet"",
""configGlossary:installationAt"": ""Philadelphia, PA"",
""configGlossary:adminEmail"": ""ksm@pobox.com"",
""configGlossary:poweredBy"": ""Cofax"",
""configGlossary:poweredByIcon"": ""/images/cofax.gif"",
""configGlossary:staticPath"": ""/content/static"",
""templateProcessorClass"": ""org.cofax.WysiwygTemplate"",
""templateLoaderClass"": ""org.cofax.FilesTemplateLoader"",
""templatePath"": ""templates"",
""templateOverridePath"": """",
""defaultListTemplate"": ""listTemplate.htm"",
""defaultFileTemplate"": ""articleTemplate.htm"",
""jspListTemplate"": ""listTemplate.jsp"",
""jspFileTemplate"": ""articleTemplate.jsp"",
""cachePackageTagsTrack"": 200,
""cachePackageTagsStore"": 200,
""cachePackageTagsRefresh"": 60,
""cacheTemplatesTrack"": 100,
""cacheTemplatesStore"": 50,
""cacheTemplatesRefresh"": 15,
""cachePagesTrack"": 200,
""cachePagesStore"": 100,
""cachePagesRefresh"": 10,
""cachePagesDirtyRead"": 10,
""searchEngineListTemplate"": ""forSearchEnginesList.htm"",
""searchEngineFileTemplate"": ""forSearchEngines.htm"",
""searchEngineRobotsDb"": ""WEB-INF/robots.db"",
""dataStoreClass"": ""org.cofax.SqlDataStore"",
""redirectionClass"": ""org.cofax.SqlRedirection"",
""dataStoreName"": ""cofax"",
""dataStoreDriver"": ""com.microsoft.jdbc.sqlserver.SQLServerDriver"",
""dataStoreUrl"": ""jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon"",
""dataStoreUser"": ""sa"",
""dataStorePassword"": ""dataStoreTestQuery"",
""dataStoreTestQuery"": ""SET NOCOUNT ON;select test='test';"",
""dataStoreLogFile"": ""/usr/local/tomcat/logs/datastore.log"",
""dataStoreInitConns"": 10,
""dataStoreMaxConns"": 100,
""dataStoreConnUsageLimit"": 100,
""dataStoreLogLevel"": ""debug"",
""servlet-name"": ""cofaxEmail"",
""servlet-class"": ""org.cofax.cds.EmailServlet"",
""mailHostOverride"": ""mail2""}
""servlet-name"": ""cofaxAdmin"",
""servlet-class"": ""org.cofax.cds.AdminServlet""},
""servlet-name"": ""fileServlet"",
""servlet-class"": ""org.cofax.cds.FileServlet""
""servlet-name"": ""cofaxTools"",
""servlet-class"": ""org.cofax.cms.CofaxToolsServlet"",
""templatePath"": ""toolstemplates/"",
""logLocation"": ""/usr/local/tomcat/logs/CofaxTools.log"",
""dataLogLocation"": ""/usr/local/tomcat/logs/dataLog.log"",
""dataLogMaxSize"": """",
""removePageCache"": ""/content/admin/remove?cache=pages&id="",
""removeTemplateCache"": ""/content/admin/remove?cache=templates&id="",
""fileTransferFolder"": ""/usr/local/tomcat/webapps/content/fileTransferFolder"",
""cofaxEmail"": ""/cofaxutil/aemail/*"",
""cofaxAdmin"": ""/admin/*"",
""fileServlet"": ""/static/*"",
""cofaxTools"": ""/tools/*""},
""taglib-uri"": ""cofax.tld"",
""taglib-location"": ""/WEB-INF/tlds/cofax.tld""}}}";
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("System.Text.Json version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];