Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to deserialize classes with multiple constructors with Json.NET [duplicate]

I have a type that I don't control with multiple constructors, equivalent to this one:

    public class MyClass
    {
        private readonly string _property;

        private MyClass()
        {
            Console.WriteLine("We don't want this one to be called.");
        }

        public MyClass(string property)
        {
            _property = property;
        }

        public MyClass(object obj) : this(obj.ToString()) {}

        public string Property
        {
            get { return _property; }
        }

    }

Now when I try to deserialize it, the private parameterless constuctor is called and the property is never set. The test:

    [Test]
    public void MyClassSerializes()
    {
        MyClass expected = new MyClass("test");
        string output = JsonConvert.SerializeObject(expected);
        MyClass actual = JsonConvert.DeserializeObject<MyClass>(output);
        Assert.AreEqual(expected.Property, actual.Property);
    }

gives the following output:

We don't want this one to be called.

  Expected: "test"
  But was:  null

How can I fix it, without changing the definition of MyClass? Also, this type is a key deep in the definition of the objects that I really need to serialize.

like image 365
Grzenio Avatar asked Jul 10 '14 14:07

Grzenio


People also ask

How do I deserialize a JSON object?

Implement deserialization by doing the following steps in the Read () method: Parse JSON into a JsonDocument. Get the properties needed to call the parameterized constructor. Create the object with the parameterized constructor. Set the rest of the properties.

How do I deserialize a class with multiple constructors?

When your class has multiple constructors, you can use the JsonConstructor attribute to specify which constructor to use during deserialization. Here’s an example: Note: JsonConstructor for System.Text.Json was added in .NET 5. This shows that it used the Person (int luckyNumber) constructor.

What are the default behaviors for jsonserializeroptions in ASP NET Core?

When you use System.Text.Json indirectly in an ASP.NET Core app, some default behaviors are different. For more information, see Web defaults for JsonSerializerOptions. By default, all public properties are serialized. You can specify properties to ignore. By default, JSON is minified. You can pretty-print the JSON.

Are JSON properties serialized or minified?

By default, all public properties are serialized. You can specify properties to ignore. The default encoder escapes non-ASCII characters, HTML-sensitive characters within the ASCII-range, and characters that must be escaped according to the RFC 8259 JSON spec. By default, JSON is minified.


1 Answers

Try adding the [JsonConstructor] attribute to the constructor you want to use when deserializing.

Change this property in your class:

[JsonConstructor]
public MyClass(string property)
{
    _property = property;
}

I have just tried it and your test passes :-)

If you can't make this change then I guess you'd need to create a CustomJsonConverter. http://james.newtonking.com/json/help/index.html?topic=html/CustomJsonConverter.htm and How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects? might help.

Here is a useful link for creating a CustomJsonConverter: https://stackoverflow.com/a/8312048/234415

like image 145
Tom Chantler Avatar answered Sep 23 '22 10:09

Tom Chantler