Home > Net >  How do I deserialize JSON where there is an array of ane/value properties along with a Location whic
How do I deserialize JSON where there is an array of ane/value properties along with a Location whic

Time:05-28

I am trying to deserialize an HTTP Request to a C# POCO class.

The JSON is:

    {
        "applicationId":"4284f0b0-61f9-4a9d-8894-766f7b9605b5",
        "deviceId":"testdevice22",
        "messageType":"cloudPropertyChange",
        "properties":[
                       {"name":"CustomerID","value":202},
                       {"name":"DeviceSerialNumber","value":"devicesa999"},
                       {"name":"Location","value":{
                                                    "alt":0,
                                                    "lat":41.29111465188208,
                                                    "lon":-80.91897192058899
                                                  }}
                    ],
    }

The POCO is:

public class CustomEventModel
{
     public string applicationId { get; set; }
     public string deviceId { get; set; }
     public List<PropertyAttribute> properties { get; set; }
}

public class PropertyAttribute
{
    public string name { get; set; }

    public string value { get; set; }
}

In my Function App I have:

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    var propertyChangeData = JsonConvert.DeserializeObject<CustomEventModel>(requestBody);

The Exception Message is: 2022-05-27T23:14:42.141 [Error] Error in CustomEventModel: Unexpected character encountered while parsing value: {. Path 'properties[7].value', line 1,

It is all related to the Location item. How do I solve this?

CodePudding user response:

The value of "Location" is

{
    "alt":0,
    "lat":41.29111465188208,
    "lon":-80.91897192058899
}

this is a complex object while the other "values" are not. They aren't even the same type. One solution is to create a custom deserializer as documented here: https://www.newtonsoft.com/json/help/html/CustomJsonConverterGeneric.htm

Then write the one-way conversion from the various value types with a custom type (e.g. CustomValue)

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

where your PropertyAttribute class now looks like this:

public class PropertyAttribute
{
    public PropertyAttribute() {}
    public PropertyAttribute(object value)
    {
        //handle the various types of input in the constructor
    }
    public string name { get; set; }

    public CustomValue value { get; set; }
}

now you can deserialize using your custom value converter like this:

var thing = JsonConvert.DeserializeObject<CustomEventModel>(json, new CustomValueConverter());

CodePudding user response:

just change a type of a value property from string to object and add Location class

public class PropertyAttribute
{
    public string name { get; set; }

    private object _value;

    public object value
    {
        get
        {

            if (_value as JObject !=null)
            return  ((JObject)_value).ToObject<Location>();
            return _value?.ToString();
        }

        set { _value = value; }
    }
}

public class Location
{
    public int alt { get; set; }
    public double lat { get; set; }
    public double lon { get; set; }
}

how to use

var propertyChangeData = JsonConvert.DeserializeObject<CustomEventModel>(requestBody);
    
Location location = (Location) propertyChangeData.properties.Where(p => p.name=="Location").FirstOrDefault().value;

string DeviceSerialNumber = (string) propertyChangeData.properties.Where(p => p.name=="DeviceSerialNumber").FirstOrDefault().value;
  • Related