Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I serialize a C# 'single case union type'-like object to its underlying value and back? [duplicate]

I am modeling a domain, and for a select few properties, even though their values are simple, I don't want to use a built-in integral (e.g. int) or a very general type (e.g. System.Guid).

So I introduced some simple 'wrapper' types. Combined with implicit operators I am happy with the result:

class Order
{
    public Price Price { get; set; }
}

order.Price = 4.95m;

Where Price 'wraps' decimal and stores the value in a private field named value.

I am now serializing objects to JSON, and I would like the object above to be serialized like this:

{
    "Price": 4.95
}

But so far I have only been able to serialize it like this, by making the field a public property:

{
    "Price": {
        "Value": 4.95
    }
}

Do you know of a way (preferably with NewtonSoft.Json) to serialize, and deserialize, in the way I described?

like image 919
Michiel van Oosterhout Avatar asked Sep 05 '25 03:09

Michiel van Oosterhout


1 Answers

You can do this with a custom converter. For example:

public class PriceConverter : JsonConverter<Price>
{
    public override Price ReadJson(JsonReader reader, Type objectType, Price existingValue, 
        bool hasExistingValue, JsonSerializer serializer)
    {
        var value = Convert.ToDecimal(reader.Value);
        return new Price { Value = value };
    }

    public override void WriteJson(JsonWriter writer, Price value, JsonSerializer serializer)
    {
        writer.WriteValue(value.Value);
    }
}

Now you just need to tell JSON.Net to use the converter. One way is to add it to your serialiser settings:

//Create the settings object and add the converter
var settings = new JsonSerializerSettings();
settings.Converters.Add(new PriceConverter());

//Use the settings
var json = JsonConvert.SerializeObject(order, settings);
var newOrder = JsonConvert.DeserializeObject<Order>(json, settings);

Alternatively, use an attribute to tell JSON.Net which converter to use, either on the property:

public class Order
{
    [JsonConverter(typeof(PriceConverter))]
    public Price Price { get; set; }
}

Or on the class:

[JsonConverter(typeof(PriceConverter))]
public class Price 
{
    public decimal Value { get; set; }  
}
like image 73
DavidG Avatar answered Sep 07 '25 21:09

DavidG