rpgmaker / NetJSON

Faster than Any Binary? Benchmark: http://theburningmonk.com/2014/08/json-serializers-benchmarks-updated-2/
MIT License
225 stars 29 forks source link

Nullable<CustomType> Bug #206

Closed ghost closed 5 years ago

ghost commented 5 years ago

I cant seem to find anything to confirm/deny whether nullable types are supported, but attempting to deserialise the following breaks NetJSON as it appears to get stuck in an endless loop.

public class NullableEntity
{
    public Guid? Id { get; set; }
    public ValueObject? Value { get; set; }
}

public struct ValueObject
{
    public string Value { get; set; }
}

private static readonly NetJSONSettings Settings = new NetJSONSettings { DateFormat = NetJSONDateFormat.ISO, TimeZoneFormat = NetJSONTimeZoneFormat.Utc };

[TestMethod]
public void HandlesNullable()
{
    var nullable = new NullableEntity { Id = Guid.NewGuid(), Value = new ValueObject{ Value = "Test" }};
    var serialised = NetJSON.NetJSON.Serialize(nullable, Settings);
    var deserialised = NetJSON.NetJSON.Deserialize<NullableEntity>(serialised, Settings); // Gets stuck here
    Assert.AreEqual(nullable.Id, deserialised.Id);
    Assert.AreEqual(nullable.Value.Value, deserialised.Value.Value);

    nullable = new NullableEntity();
    serialised = NetJSON.NetJSON.Serialize(nullable, Settings);
    deserialised = NetJSON.NetJSON.Deserialize<NullableEntity>(serialised, Settings);
    Assert.IsFalse(deserialised.Id.HasValue);
}

Some minor debugging using the NetJSON source seems to indicate the issue is in NetJSONGeneratedAssembly!NullableEntityClass.CreateClassOrDictValueObject(char* value, ref int value, NetJSON.NetJSONSettings value) emitted method where it is probably getting stuck in the while loop. The stack trace is as follows, with NetJSONSettings.HasOverrideQuoteChar.get() being hit endlessly whilst it is processing my NullableEntity.Value property:

NetJSON.Core.dll!NetJSON.NetJSONSettings.HasOverrideQuoteChar.get() Line 97
NetJSONGeneratedAssembly!NullableEntityClass.CreateClassOrDictValueObject(char* value, ref int value, NetJSON.NetJSONSettings value)
NetJSONGeneratedAssembly!NullableEntityClass.SetNullableValueObject(char* value, ref int value, ref Serialisation.Tests.NetJSONTests.ValueObject? value, string value, NetJSON.NetJSONSettings value)
NetJSONGeneratedAssembly!NullableEntityClass.CreateClassOrDictNullableValueObject(char* value, ref int value, NetJSON.NetJSONSettings value)
NetJSONGeneratedAssembly!NullableEntityClass.SetNullableEntity(char* value, ref int value, Serialisation.Tests.NetJSONTests.NullableEntity value, string value, NetJSON.NetJSONSettings value)
NetJSONGeneratedAssembly!NullableEntityClass.CreateClassOrDictNullableEntity(char* value, ref int value, NetJSON.NetJSONSettings value)
NetJSONGeneratedAssembly!NullableEntityClass.ReadNullableEntity(string value, NetJSON.NetJSONSettings value)
NetJSON.Core.dll!NetJSON.NetJSON.Deserialize<Serialisation.Tests.NetJSONTests.NullableEntity>(string json, NetJSON.NetJSONSettings settings) Line 3471
Serialisation.Tests.dll!Serialisation.Tests.NetJSONTests.HandlesNullable() Line 141
rpgmaker commented 5 years ago

Thanks for the find. I will look into it.

rpgmaker commented 5 years ago

Sorry, i am still working on it. I fixed a segment of the issue but I am not still getting the expected result. It does not get stuck in an endless loop, but it is not setting the value correctly either.

ghost commented 5 years ago

Thanks for the update, happy that you're looking at it!

rpgmaker commented 5 years ago

Sorry been busy with other things that came up. I will look at it soon and get back to you.

rpgmaker commented 5 years ago

Please test when you get a chance. Sorry it took so long, was busy with personal stuff.

rpgmaker commented 5 years ago

The solution has also been pushed to nuget already