Cannot Get JsonConvert.DeserializeObject with oData to Work - json

I a class that looks like so:
public class AccountAddress
{
[Key]
public int accountNumber { get; set; }
public int rowNumber { get; set; }
public string civicaddress { get; set; }
public AccountAddress()
{
//Default constructor
}
}
There is a rest API that returns a List of AccountAddress as oData that looks like this to a variable "result":
{
"#odata.context":"http://localhost:52139/odata/$metadata#WEB_V_CIVIC_ADDRESS/Values.Classes.Entities.AccountAddress","value":[
{
"#odata.type":"#Values.Classes.Entities.AccountAddress","accountNumber":123456,"rowNumber":0,"civicaddress":"123 FAKE EAST DRIVE"
},{
"#odata.type":"#Values.Classes.Entities.AccountAddress","accountNumber":123457,"rowNumber":0,"civicaddress":"123 FAKE WEST DRIVE"
}
]
}
When I try to use:
var addressAccountLookup = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AccountAddress>>(result);
I get an error
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[ATPublicTAX.Regina.ca.Values.Classes.Entities.AccountAddress]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
Any help on this would be greatly appreciated.
Thanks.

You're passing the entire object to your deserialization method. You need to pass only the array, which is what it's asking you to do.
JArray array = (JArray) result["value"];
var addressAccountLookup = Newtonsoft.Json.JsonConvert.DeserializeObject<List<AccountAddress>>(array);
Something like that should work.

The solution that I got to work is create a class:
private class oDataResponse<T>
{
public List<T> Value { get; set; }
}
Then deserialize like this:
var oDataRespone = Newtonsoft.Json.JsonConvert.DeserializeObject<oDataResponse<AccountAddress>>(result);

Related

Newtonsoft.DeserializeObject for generic class

I have a JSON response like the following
{
"msg": "1",
"code": "2",
"data": [
{
"a": "3",
"b": "4"
}
],
"ts": "5"
}
I would like to create a generic class
public class DTWSResponse<T>
{
public string msg { get; set; }
public string code { get; set; }
public T data { get; set; }
public long ts { get; set; }
}
so this class will map each of the variable. But the data portion can be generic, i.e. it might have different format rather than 2 variables a and b.
So I create another class
public class DTProf
{
public string a { get; set; }
public string b { get; set; }
}
and in my code, I call as
DTWSResponse<DTProf> prof = JsonConvert.DeserializeObject<DTWSResponse<DTProf>>(json);
But I'm getting the following error
An exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll but was not handled in user code
Additional information: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'DataTransfer.DTProfile' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'data', line 1, position 40.
Any ideas?
Use the correct type for the generic type argument
the JSON shown has a collection for the data property. So use a collection as the type argument. No need to change the generic class.
var prof = JsonConvert.DeserializeObject<DTWSResponse<IList<DTProf>>>(json);
var a = prof.data[0].a;
Make data a generic list and you should be fine...
public class DTWSResponse<T>
{
public string msg { get; set; }
public string code { get; set; }
public IList<T> data { get; set; }
public long ts { get; set; }
}

Custom serialization in Service Stack using DeSerializeFn

In servicestack, I am trying to process a webhook which sends the following JSON body to a service stack endpoint:
{
"action": "actionType1",
"api_version": "1.00",
"data": {
"id": "a8d316b8-10a7-4440-a836-9bd354f656db",
//VARIABLE other properties / structure
}
}
Which I am trying to map to the following request object:
[Route("/public/Webhookhandler", HttpVerbs.Post)]
public class MyCustomRequst
{
public string action { get; set; }
public string api_version { get; set; }
public string data { get; set; } //Will be the remaining JSON
}
However, when the service stack framework processes this - the value in "data" is the correct part of the JSON body, but with all of the quotes removed - so it is no longer valid.
I have tried to override the serialization for the whole request object using something like this:
JsConfig<MyCustomRequst>.DeSerializeFn = DeserializeMyRequestDto;
public MyCustomRequst DeserializeMyRequestDto(string rawBody)
{
var result = rawBody.FromJson<MyCustomRequst>();
return result
}
But even in this case, the value of the "rawBody" variable is still the correct JSON data but with all the quotes removed, e.g.
{
action:actionType1,
api_version:1.00,
data:{id:a8d316b8-10a7-4440-a836-9bd354f656db}
}
Am I doing something wrong here? I am unsure whether I am trying to make service stack do something it is not intended to do, or whether I am missing something that would make this work.
Any help would be appreciated :-)
Your DTO should closely match the shape of the JSON, if it's always a flat object you can use a string Dictionary, e.g:
[Route("/public/Webhookhandler", HttpVerbs.Post)]
public class MyCustomRequst
{
public string action { get; set; }
public string api_version { get; set; }
public Dictionary<string,string> data { get; set; }
}
If it's a more nested object structure you can use a JsonObject for a more flexible API to parse dynamically.

JSON array is converting to a generic list, but not converting to a generic collection. Why?

I am sending a Json Array from the client web application to asp.net webapi.
For example,
{
"SurveyId":3423,
"CreatorId":4235,
"GlobalAppId":34,
"AssociateList":[
{"AssociateId":4234},
{"AssociateId":43},
{"AssociateId":23423},
{"AssociateId":432}
],
"IsModelDirty":false,
"SaveMode":null
}
Here Associate List is a JSON Array,
Usually it will automatically serialize to a List<> object.
Using the below code ,i am posting the response to the WebApi
public IEnumerable<Associate> Post(ResponseStatus responseStatus)
{
return this.responsestatusrepository.ResponseStatusCheck(responseStatus);
}
The ResponseStatus class is shown below.
public class ResponseStatus : AppBaseModel
{
public int SurveyId { get; set; }
public int CreatorId { get; set; }
public int GlobalAppId { get; set; }
public List<Associate> AssociateList { get; set; }
}
I have changed the List<> to Collection<> as a part of my code analysis correction.
ie, public Collection<Associate> AssociateList { get; set; }
But it is always getting a null value when we are using collection instead of List. Is there any specific reason for this?
Ok, I think I will have to answer this in an indirect way.
What you are passing on to the server is an array of objects (in JSON format), but once you start processing this in C# the array of objects is now treated as a single c# object. Inside this object, your model expects one of the fields to be a Collection of Associate.
Right, when I work with JSON data similar to whats mentioned in this case - I prefer to use Newtonsofts' JOject.
So here is how I made the C# object with the JSON data you provided:
Used your model:
public class ResponseStatus
{
public int SurveyId { get; set; }
public int CreatorId { get; set; }
public int GlobalAppId { get; set; }
public Collection<Associate> AssociateList { get; set; }
}
public class Associate
{
public int AssociateId { get; set; }
}
Made a routine which takes string (the JSON data), and returns an object of type ResponseStatus:
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
---------------------------------------------------------------------
public static ResponseStatus GetResponseStatusObject(string jsonData)
{
JObject jObject = JObject.Parse(jsonData);
return jObject.ToObject<ResponseStatus>();
}
Now when I call this method and pass on the exact same JSON data which you provided, I get this:
This might not directly solve your problem, but hopefully guide you in the right direction in understanding array/object serialization when working with JavaScript/C#.
Best of luck!

deserialize object that contains list of int as property

I'm trying to Deserialize a Json into my object using Newtonsoft.Json.JsonConvert.
My json is:{"SelectedContentsID[]":"31807,32493,39517","pageSize":"20","SisconContentSubDialogEnum":"0","searchCriteria":"","pageIndex":"1"}
and the respective class is:
[DataContract]
public class ContentGetHandlerDTO : ListBaseHandlerDto
{
[DataMember(Name = "SelectedCourseId")]
public int SelectedCourseId { get; set; }
[DataMember]
public System.Collections.Generic.List<int> SelectedContentsID { get; set; }
public ContentGetHandlerDTO() {
this.SelectedContentsID = new System.Collections.Generic.List<int>();
}
}
the ListBaseHandlerDto is just a class that contains some commons properties.
The problem is, the deserializer method is just ignoring the list of int and bringing a null list.
Your Json looks incorrect, it should look like this:
{
"SelectedContentsID":[31807,32493,39517],
"pageSize":"20",
"SisconContentSubDialogEnum":"0",
"searchCriteria":"",
"pageIndex":"1"
}
specifically look at your SelectedContentsID,
you had:
"SelectedContentsID[]":"31807,32493,39517"
when a json int array should look like this:
"SelectedContentsID":[31807,32493,39517]
here is a pretty good reference if you ever get confused - http://www.w3schools.com/json/json_syntax.asp

Serializing Multidimensional array to JSON with ServiceStack

Returning the following object excludes the property "coordinates" from the JSON.
What am I doing wrong?
[Route("/GeozonePolygon/{ZoneType}")]
public class RequestGeozonePolygon{
public int ZoneType { get; set; }
}
public class ResponseGeozonePolygon{
public FeatureCollection Result { get; set; }
public ResponseStatus ResponseStatus { get; set; }
}
public class GeozonePolygon : Service {
public ResponseGeozonePolygon Any(RequestGeozonePolygon request){
return new ResponseGeozonePolygon() { Result = (new DAL.GeoZone()).GetZoneGeoJsonByType(request.ZoneType) };
}
}
These are the involved types:
public class Geometry {
public string type {
get { return GetType().Name; }
}
}
public class Feature {
public string type {
get { return GetType().Name; }
}
public Geometry geometry { get; set; }
public object properties { get; set; }
}
public class FeatureCollection {
public string type {
get { return GetType().Name; }
}
public Feature[] features { get; set; }
}
public class MultiPolygon : Geometry {
public double[][][][] coordinates { get; set; }
}
FeatureCollection property geometry contains a MultiPolygon object.
Thanks in advance!
You are serializing only the properties of the Geometry object, even though the actual object is a MultiPolygon. As explained by Mythz,
As there is no concept of 'type info' in the JSON spec, in order for inheritance to work in JSON Serializers they need to emit proprietary extensions to the JSON wireformat to include this type info - which now couples your JSON payload to a specific JSON serializer implementation.
To enable support for polymorphic Geometry objects in Servicestack.text, add a type specific config setting to add 'type info' to the output. i.e.:
JsConfig<Geometry>.ExcludeTypeInfo = false;
(may also require adding an interface. See the tests for Polymorphic List serialization. and tests for Polymorphic Instance serialization. for examples)
If you are loath to expose type info in your json, you can use custom serializers as an alternative solution.