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;