timkado
timkado

Reputation: 2052

Json.Net (8.0) Error creating StringEnumConverter on Mono 4.5 Mac

I am having trouble understanding the issue I am getting with Json.Net on Mac. I am trying to serialize/deserialize objects like the one below.

The code runs without issues on Windows but generates a Newtonsoft.Json.JsonException "Error creating StringEnumConverter" on Mac (also shown in the image). I am hoping someone does see something in the code or error message that could point me in the right direction. The object contains many more fields but the error sounds like it has something to do with the enums. I am building in Xamarin 6 / Mono .Net 4.5 and I am using Json.Net 8.0.3 for .Net 4.5. Any help greatly appreciated.

Edit 1: Removing the JsonConverter(typeof(StringEnumConverter)) decoration avoids the exception - however, enums are serialized as integers again.

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace Lib
{
    [DataContract(IsReference = true)]
    public class Construction : LibraryComponent
    {
        public Construction() { }
        public override string ToString() { return Serialization.Serialize(this); }

        [DataMember]
        public string Construction { get; set; } = "defaultConstruction";

        ...

        [DataMember, JsonConverter(typeof(StringEnumConverter)), DefaultValue(InConvAlgo.TARP)]
        public InConvAlgo SurfaceConvectionModelInside { get; set; } = InConvAlgo.TARP;

        [DataMember, JsonConverter(typeof(StringEnumConverter)), DefaultValue(OutConvAlgo.DOE2)]
        public OutConvAlgo SurfaceConvectionModelOutside { get; set; } = OutConvAlgo.DOE2;

        ...

        [DataMember, DefaultValue(1)]
        public int Priority { get; set; } = 1;
    }

    public enum InConvAlgo { Simple, TARP, TrombeWall, AdaptiveConvectionAlgorithm };
    public enum OutConvAlgo { DOE2, TARP, MoWiTT, SimpleCombined, AdaptiveConvectionAlgorithm }; //  DOE-2,  

}

enter image description here

Upvotes: 4

Views: 4901

Answers (5)

fkorsa
fkorsa

Reputation: 751

This is a stripping issue. Because the parameter-less constructor is never used explicitly in your code, it gets stripped from your build.

To avoid it, you need to force inclusion of that constructor in your build. There is a range of ways to do that, several of which are described in other answers. I'll add another one specific to Unity3D, which I think is cleaner.

There is a project that is a fork of Json.NET dedicated to tweaking it for Unity3D, which contains a helper class that fixes exactly that: https://github.com/jilleJr/Newtonsoft.Json-for-Unity/wiki/Fix-AOT-using-AotHelper

In the case of StringEnumConverter, you can add this line anywhere in your code and it will solve the issue:

AotHelper.EnsureType<StringEnumConverter>();

Upvotes: 3

Jai
Jai

Reputation: 466

StringEnumConverter doesn't have its own public constructor which is needed by code. You can use JsonStringEnumConverter which provides public constructor.

replace: [JsonConverter(typeof(StringEnumConverter))] ====> [JsonConverter(typeof(JsonStringEnumConverter))]

And it will work.

Upvotes: 6

Daztane
Daztane

Reputation: 31

I had the same issue with mono.

A simple workaround which works for me was to create a class that inherit from StringEnumConverter and use it.

That avoid you from copying the source code of this converter (Json.net has a lot of "utils" class).

No more issue after that.

Upvotes: 3

ikeo
ikeo

Reputation: 21

I recently ran into this same problem. Including StringEnumConverter in my source, as suggested by Adi Unnithan, requires that you additionally copy some Util classes. Not to mention that changing the namespace of that class in the copied code, probably doesn't jibe with the license. Not changing it puts it in contention with any other referenced version of json.net.

The only solution that I could find was to fork Json.net and build on Mono, then reference the resulting dll in the main project.

Upvotes: 0

Adi Unnithan
Adi Unnithan

Reputation: 303

I hit this in Json.Net 9.01 with Unity3D (runs Mono). The inner exception was something like 'No parameterless constructor for StringEnumConverter'.

I wasn't entirely sure what was going on but I worked around this by duplicating StringEnumConverter into my project under my own namespace/assembly.

Upvotes: 0

Related Questions