Nathan Bruet
Nathan Bruet

Reputation: 222

Deserialize string contains int with comma

I can't deserialize number with comma in json to int. It throw this exception :

Newtonsoft.Json.JsonReaderException : 'Could not convert string to integer: 24,992. Path 'Requests', line 1

This is my code :

public class PriceModel
{
    public DateTime Date { get; set; }
    public int Requests { get; set; }
    public decimal Price { get; set; }
}
string json = "{\"Date\":\"2018-03-23\",\"Requests\":\"24,992\",\"Price\":\"95.96\"}";

PriceModel value = JsonConvert.DeserializeObject<PriceModel>(json, new JsonSerializerSettings
{
    Culture = new CultureInfo("en-US")
});

I want that the "Requests" property have the value 24992.

Is there a solution to resolve this problem ?

Thanks

Upvotes: 6

Views: 2885

Answers (3)

David Bremner
David Bremner

Reputation: 406

I ran into this issue today and came up with a different solution.

First, define a JsonConverter<int> that accepts the format.

public sealed class ThousandsIntConverter : JsonConverter<int>
{
    public override int ReadJson(
        JsonReader reader,
        Type objectType,
        int existingValue,
        bool hasExistingValue,
        JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            throw new JsonSerializationException("Cannot unmarshal int");
        }

        var value = (string)reader.Value;
        const NumberStyles style = NumberStyles.AllowThousands;
        var result = int.Parse(value, style, CultureInfo.InvariantCulture);
        return result;
    }

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

Now add the [JsonConverter(typeof(ThousandsIntConverter))] attribute to the property that you want converted.

The property will be serialized even if it contains commas and it will be deserialized without them.

Upvotes: 0

Rudresha Parameshappa
Rudresha Parameshappa

Reputation: 3926

Ok after some research came up with following solution where you don't need to change any type or anything and it works as per your requirement.

While deserializing don't use return type var instead use PriceModel and then other things will remain same.

Create new Class ProcessChildModel which inherits from ProcessModel and overrides Requests property.

    public class PriceModel
    {
        public DateTime Date { get; set; }
        public int Requests { get; set; }
        public decimal Price { get; set; }
    }

    public class PriceModelChild : PriceModel
    {
        public new string Requests
        {
            set
            {
                int num;
                if (int.TryParse(value, NumberStyles.AllowThousands,
                    CultureInfo.InvariantCulture, out num))
                {
                    base.Requests = num;
                }

            }
        }
    }

Then use the new child model to deserialize the data

string json = "{\"Date\":\"2018-03-23\",\"Requests\":\"24,992\",\"Price\":\"95.96\"}";
PriceModel value = JsonConvert.DeserializeObject<PriceModelChild>(json);

Upvotes: 5

vbnet3d
vbnet3d

Reputation: 1141

Redefine your class:

public class PriceModel
{
    public DateTime Date { get; set; }
    public string Requests { get; set; }
    public decimal Price { get; set; }
}

Because the data type int cannot handle the comma. Once the object is deserialized, you can then remove the comma:

int requests;
int.TryParse(value.Requests.Replace(",",""), out requests);

Upvotes: 1

Related Questions