Closed arekbulski closed 4 years ago
You can't deserialize an array into an object, but you can have a object[]
:
var o = JSON.ToObject("[1,\"2\",3.141592]");
// o[0] == 1 long
// o[1] == "2" string
// o[2] == 3.141592 double
I made a mistake in previous example, it would need to be a decimal (not double). Could a decimal be parsed in your example code, directly, without converting from a double?
Without type information fastJSON
assumes it to be a double
, if you need decimal
then you should convert it afterwards.
Hmmm... looking at the parse code, it should be a decimal
since it does not have an exponent, I have changed fastJSON
and the tests pass, will post soon.
I was thinking of using a custom transform like this one:
class HeterogenousArray : JsonConverter<HeteroArray, object[]>
{
protected override object[] Convert (string fieldName, HeteroArray fieldValue) {...}
protected override HeteroArray Revert (string fieldName, object[] fieldValue) {...}
}
I had done some experiments with Newtonsoft but well, it sort of worked. It worked correctly on simple examples but failed in more complex structures. But it is essentially what I had in mind.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace HeterogenousArraysLab
{
class Program
{
static void Main(string[] args)
{
var x = JsonConvert.DeserializeObject<Example>("[1.2, true, \"text\"");
var json = JsonConvert.SerializeObject(x);
}
public class HeterogenousArray: JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var objectType = value.GetType();
writer.WriteStartArray();
foreach (FieldInfo member in objectType.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
writer.WriteValue(member.GetValue(value));
}
writer.WriteEndArray();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var ctor = objectType.GetConstructor(Type.EmptyTypes);
var obj = ctor.Invoke(new object[]{});
foreach (FieldInfo member in objectType.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
if (reader.Read() == false)
throw new Exception("Not enough JSON fields to match type fields.");
member.SetValue(obj, reader.Value);
}
if (reader.Read() == true)
throw new Exception("Too many JSON fields to match type fields.");
return obj;
}
public override bool CanConvert(Type objectType)
{
return objectType.IsClass && objectType.IsLayoutSequential;
}
}
[JsonConverter(typeof(HeterogenousArray))]
[StructLayout(LayoutKind.Sequential)]
class Example
{
public double Number;
public bool TrueValue;
public string Text;
}
}
}
Would you be willing and able to merge a PR adding support for heterogenous arrays into the core library? I am a maintainer on GitHub as well, Construct library for Python, so I can promise you clean code and test cases.
You can always fork fastJSON
and add your own code to it :)
Yeah true :) but I would like to pull it via NuGet. Was that a no?
Could someone point out to me, even in speculation or educated guess, if this could be done using fastJSON or other framework?
I have a heterogeneous array like
[1, 2.0, "3"]
.Can this be somehow (de)serialized using a class?