dubbbdan
dubbbdan

Reputation: 2740

Parse JSON property during deserialization

With the following portion of a JSON:

"tags": 
{
  "tiger:maxspeed": "65 mph"
}

And I have the corresponding C# class I am using to deserialize:

public class Tags
{

    [JsonProperty("tiger:maxspeed")]
    public string Maxspeed { get; set; }

}

I would like to deserialize it into an integer property instead:

public class Tags
{

    [JsonProperty("tiger:maxspeed")]
    public int Maxspeed { get; set; }

}

Is it possible to parse the numeric part of the string from the JSON to an int during deserialization?

I think I want something like:

public class Tags
{
    [JsonProperty("tiger:maxspeed")]
    public int Maxspeed 
    {
        get
        {
            return _maxspeed;
        }
        set
        {
            _maxspeed = Maxspeed.Parse(<incoming string>.split(" ")[0]);
        }
    }
}

Upvotes: 2

Views: 927

Answers (2)

Brian Rogers
Brian Rogers

Reputation: 129777

I would suggest a variation of @djv's idea. Make the string property private and put the conversion logic there. The serializer will pick it up due to the [JsonProperty] attribute, but it will not muddy up the public interface of the class.

public class Tags
{
    [JsonIgnore]
    public int MaxSpeed { get; set; }

    [JsonProperty("tiger:maxspeed")]
    private string MaxSpeedString
    {
        get { return MaxSpeed + " mph"; }
        set 
        {
            if (value != null && int.TryParse(value.Split(' ')[0], out int speed))
                MaxSpeed = speed;
            else
                MaxSpeed = 0;
        }
    }
}

Fiddle: https://dotnetfiddle.net/SR9xJ9

Alternatively you could use a custom JsonConverter to keep the conversion logic separate from the model class:

public class Tags
{
    [JsonProperty("tiger:maxspeed")]
    [JsonConverter(typeof(MaxSpeedConverter))]
    public int MaxSpeed { get; set; }
}

class MaxSpeedConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // CanConvert is not called when the converter is used with a [JsonConverter] attribute
        return false;   
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        string val = (string)reader.Value;

        int speed;
        if (val != null && int.TryParse(val.Split(' ')[0], out speed))
            return speed;

        return 0;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteValue((int)value + " mph");
    }
}

Fiddle: https://dotnetfiddle.net/giCDZW

Upvotes: 3

djv
djv

Reputation: 15774

Can you just use a different property to return the int portion of the string?

public class Tags
{

    [JsonProperty("tiger:maxspeed")]
    public string Maxspeed { get; set; }

    [JsonIgnore]
    public int MaxSpeedInt => int.Parse(Maxspeed.Split(' ')[0]);

}

Upvotes: 3

Related Questions