Error when attempting to deserialze JSON using DataContractJsonSerializer - c#

This one really has me stumped. I'm trying to deserialize the following JSON string which I get from a ASP.NET Web Service:
"{\"d\":{\"__type\":\"KPCServer.LogonResult\",\"User\":{\"UserId\":\"affaa328-5b53-430e-991a-22674ede6faf\",\"Email\":\"test#test.com\",\"Alias\":\"Mike\",\"FullName\":\"Mike Christensen\",\"Password\":\"secret\",\"Location\":\"Redmond, WA\",\"ImageUrl\":null,\"DateOfBirth\":\"\\/Date(-62135568000000)\\/\",\"LastLogon\":\"\\/Date(1350450228000)\\/\",\"UserSince\":\"\\/Date(1197980020000)\\/\",\"MailingList\":true,\"Bio\":\"Test\"},\"NewUser\":false,\"Ticket\":\"FJEjfje87fjef88fe8FAF8fA88fAjk+AFJ9fja9Fa9Ff99aJF9aFjfA99fjaBFJ7zqmlcHn9Dfw=\"}}"
I have the following types:
public class User
{
public Guid UserId { get; set; }
public string Email { get; set; }
public string Alias { get; set; }
public string FullName { get; set; }
public string Password { get; set; }
public string Location { get; set; }
public string ImageUrl { get; set; }
public DateTime DateOfBirth { get; set; }
public DateTime LastLogon { get; set; }
public DateTime UserSince { get; set; }
public bool MailingList { get; set; }
public string Bio { get; set; }
}
[DataContract(Name="KPCServer.LogonResult")]
public class LogonResult
{
[DataMember] public User User { get; set; }
[DataMember] public bool NewUser { get; set; }
[DataMember] public string Ticket { get; set; }
}
[DataContract]
[KnownType(typeof(LogonResult))]
public class Result<T>
{
[DataMember]
public T d { get; set; }
}
I then try to deserialize the string using:
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Result<T>));
Result<T> result = serializer.ReadObject(stream) as Result<T>;
return result.d;
}
Note: In the above method, T is of type LogonResult.
However, I get the following exception on ReadObject:
System.Runtime.Serialization.SerializationException was unhandled by user code
HResult=-2146233076
Message=JSON contains a '__type' member specifying the data contract name ':KPCServer.LogonResult'. The deserializer has no knowledge of any type that maps to this contract. Add the type corresponding to 'KPCServer.LogonResult' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to DataContractSerializer. You can also often eliminate this error by avoiding the use of derived types where the JSON is produced.
Source=System.ServiceModel.Web
InnerException:
If I run:
json = json.Replace("_type", "_blah");
Then everything works fine. This is using Silverlight on Windows Phone 8.

This is due to the fact that:
"\"__type\":\"KPCServer.LogonResult\""
doesn't contain a data contract namespace. This is fixed by modifying the DataContractAttribute on LogonResult:
[DataContract(Name = "KPCServer.LogonResult", Namespace="")]
public class LogonResult
{
[DataMember]
public User User { get; set; }
[DataMember]
public bool NewUser { get; set; }
[DataMember]
public string Ticket { get; set; }
}

Related

Unable to deserialize JSON in c#

I am getting the below JSON in response from a REST API.
{
"data":{
"id":123,
"zoneid":"mydomain.com",
"parent_id":null,
"name":"jaz",
"content":"172.1 6.15.235",
"ttl":60,
"priority":null,
"type":"A",
"regions":[
"global"
],
"system_record":false,
"created_at":"2017-09-28T12:12:17Z",
"updated_at":"2017-09-28T12:12:17Z"
}
}
and trying to resolve using below code but that doesn't result in a correctly deserialized type.
var model = JsonConvert.DeserializeObject<ResponseModel>(response);
below is a class according the field I received in JSON response.
public class ResponseModel
{
public int id { get; set; }
public string zone_id { get; set; }
public int parent_id { get; set; }
public string name { get; set; }
public string content { get; set; }
public int ttl { get; set; }
public int priority { get; set; }
public string type { get; set; }
public string[] regions { get; set; }
public bool system_record { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
}
What is missing?
You're missing a wrapper class.
public class Wrapper
{
public ResponseModel data {get;set}
}
and then do:
var model = JsonConvert.DeserializeObject<Wrapper>(response).data;
to get the instance of your ResponseModel out the data property.
You can deduct this from your json:
{ "data":
{ "id":123, /*rest omitted */ }
}
The type that will receive this JSON needs to have a property named data. The suggested Wrapper class acts as that type.
According to json2csharp website, your model seems to be incorrect. Try this one :
public class ResponseModel
{
public int id { get; set; }
public string zoneid { get; set; }
public object parent_id { get; set; }
public string name { get; set; }
public string content { get; set; }
public int ttl { get; set; }
public object priority { get; set; }
public string type { get; set; }
public List<string> regions { get; set; }
public bool system_record { get; set; }
public DateTime created_at { get; set; }
public DateTime updated_at { get; set; }
}
public class RootObject
{
public ResponseModel data { get; set; }
}
Here a cool trick you can do in Visual Studio 2015-2017 where it generates the the correct class if you just copy the JSON (ctrl + c).
You need to create a new class in visual studio and once inside the class go to Edit menu -> Paste special -> paste JSON As Classes.
Steps to generate json class
This will generate the C# object for that json for you and save you all the hassle :)
Your model does not match your response - it matches the data property. Simply wrap another object round it
public class ResponseData
{
public ResponseModel Data {get; set; {
}
and then
var model = JsonConvert.DeserializeObject<ResponseData>(response);

AutoMapper - object to object different namespaces

I have a scenario where we have two services that reference an object definition dll which is called SLInterface.dll. This is just a compilation of our object model. This object is huge so I'll tone it down and give a snippet of the code:
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ComponentModel;
namespace SLInterface
{
[DataContract(Namespace = Utilities.strNamespace)]
public class EntityShipment
{
public EntityShipment()
{
lstEntityResponseStatus = new List<EntityResponseStatus>();
}
[DataMember]
public EntityAddress objShipTo
{
get;
set;
}
[DataMember]
public EntityToolKit ToolKit { get; set; }
[DataMember]
public List<EntityResponseStatus> lstEntityResponseStatus
{
get;
set;
}
}
}
namespace SLInterface
{
public class EntityAddress
{
[DataMember]
public String strCustomerID
{
get;
set;
}
[DataMember]
public String strCompanyName
{
get;
set;
}
[DataMember]
public String strContactName
{
get;
set;
}
[DataMember]
public String strAddressLine1
{
get;
set;
}
[DataMember]
public String strAddressLine2
{
get;
set;
}
[DataMember]
public String strAddressLine3
{
get;
set;
}
[DataMember]
public String strCity
{
get;
set;
}
[DataMember]
public String strState
{
get;
set;
}
[DataMember]
public String strPostalCode
{
get;
set;
}
[DataMember]
public String strCountryCode
{
get;
set;
}
[DataMember]
public String strCountryName
{
get;
set;
}
[DataMember]
public String strPhoneNumber
{
get;
set;
}
[DataMember]
public String strFaxNumber
{
get;
set;
}
[DataMember]
public Boolean blnRBDICheck
{
get;
set;
}
[DataMember]
public Boolean blnIsRBDI
{
get;
set;
}
[DataMember]
public String strPlantID
{
get;
set;
}
[DataMember]
public String strAccountNumber
{
get;
set;
}
[DataMember]
public String strEmailAddress
{
get;
set;
}
[DataMember]
public Boolean blnBlindShip
{
get;
set;
}
}
}
And Then there is another definition for toolkit and for EntityResponseStatus which I can post if it is needed.
We have a scenario where from ServiceA, we need to pass this object to ServiceB. We can't just pass this object that is filled during ServiceA as it is a different namespace. So we're trying to use AutoMapper so we don't have to map each property and it values individually.
Here is our AutoMapperCode:
public class ES
{
public ServiceA.SLInterface.EntityResponseStatus CallES(string strPrinterPath, string strShipmentNumber, string strCompanyCode)
{
Mapper.CreateMap<ServiceA.SLInterface.EntityShipment, ServiceB.SLInterface.EntityShipment>();
ServiceA.SLInterface.EntityResponseStatus objERS = new ServiceA.SLInterface.EntityResponseStatus();
objERS.StatusType = ServiceA.SLInterface.ResponseStatusType.SUCCESS;
ServiceA.SLInterface.EntityShipment objES = new ServiceA.SLInterface.EntityShipment();
objES = FillES(objES, strShipmentNumber, strCompanyCode);
Sage300 obj300 = new Sage300();
objES = obj300.Pull(objES);
ServiceB.SLInterface.EntityShipment objESES = new ServiceB.SLInterface.EntityShipment();
try
{
objESES = Mapper.Map<ServiceB.SLInterface.EntityShipment>(objES); //This is the line that we blow up on. The error message is "Missing type map configuration or unsupported mapping."
}
catch(AutoMapperConfigurationException amce)
{
ServiceA.SLInterface.EntityResponseStatus objERS1 = new ServiceA.SLInterface.EntityResponseStatus();
objERS1.Message = amce.Message;
}
catch (AutoMapperMappingException amme)
{
ServiceA.SLInterface.EntityResponseStatus objERS1 = new ServiceA.SLInterface.EntityResponseStatus();
objERS1.Message = amme.Message;
}
objESES = ServiceB.CallESShip(objESES,strPrinterPath);
return objERS;
}
In the try catch is where we get the error message
objESES = Mapper.Map<ServiceB.SLInterface.EntityShipment>(objES); //This is the line that we blow up on. The error message is "Missing type map configuration or unsupported mapping."
Both object models are exactly the same. Do we have to do a mapping for each object in the main object. Right now, we are thinking with the code that we have that it would be mapping everything from the root down exactly the same and then transferring over the data. Any help would be appreciated.
Thanks!

Convert string to Json in c#

I want to convert string to json, but all I get is null or error
For example I want to convert this string:
string json =
"{\"$id\":\"1\",\"Result\":{\"$id\":\"2\",\"ListRate\":[{\"$id\":\"3\",\"Title\":\"fetures\",\"ShoppingRateId\":3,\"Rate\":0.0},{\"$id\":\"4\",\"Title\":\"Graphic\",\"ShoppingRateId\":2,\"Rate\":0.0},{\"$id\":\"5\",\"Title\":\"worth of price\",\"ShoppingRateId\":1,\"Rate\":0.0}],\"MyRate\":[{\"$id\":\"6\",\"Title\":\"worth of price\",\"ShoppingRateId\":1,\"Rate\":1.5},{\"$id\":\"7\",\"Title\":\"Graphic\",\"ShoppingRateId\":2,\"Rate\":2.0},{\"$id\":\"8\",\"Title\":\"fetures\",\"ShoppingRateId\":3,\"Rate\":2.0}],\"ListRated\":[{\"$id\":\"9\",\"Title\":\"worth of price\",\"ShoppingRateId\":1,\"Rate\":30.0,\"theCount\":1,\"theSum\":1.5},{\"$id\":\"10\",\"Title\":\"Graphic\",\"ShoppingRateId\":2,\"Rate\":40.0,\"theCount\":1,\"theSum\":2.0},{\"$id\":\"11\",\"Title\":\"fetures\",\"ShoppingRateId\":3,\"Rate\":40.0,\"theCount\":1,\"theSum\":2.0}]},\"StatusCode\":\"Created\",\"Description\":null}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
var myclass = Newtonsoft.Json.JsonConvert.DeserializeObject<ProductDto>(json);
And Class of product:
public class RootObject
{
public string id { get; set; }
public ProductDto Result { get; set; }
public string StatusCode { get; set; }
public object Description { get; set; }
}
public class ProductDto
{
public string id { get; set; }
public IQueryable<MyRateDto> ListRate { get; set; }
public IQueryable<MyRateDto> MyRate { get; set; }
public IQueryable<ShoppingRateDto> ListRated { get; set; }
}
public class ShoppingRateDto
{
public string id { get; set; }
public string Title { get; set; }
public long ShoppingRateId { get; set; }
public double Rate { get; set; }
public int theCount { get; set; }
public double theSum { get; set; }
}
public class MyRateDto
{
public string id { get; set; }
public string Title { get; set; }
public long ShoppingRateId { get; set; }
public double Rate { get; set; }
}
I'm a bit confused how should I convert it .
Also I have using "RootObject" instead of "ProductDto", but nothing changed ...
Some of error:
Additional information: The best overloaded method match for
'Newtonsoft.Json.JsonConvert.DeserializeObject(string)'
has some invalid arguments
Additional information: Cannot create and populate list type
System.Linq.IQueryable`1[Site.Model.MyRateDto]. Path 'Result.ListRate'
Seems like the error is a decent hint. Instead of using IQueryable (basically any interface collections), try using a concrete collection. e.g. List<T>
Serializers have to work with concrete classes to be able to instantiate them through reflection. When they are reading class definitions, and they come across interfaces, seldom can the serializer make a choice on the correct implementation. Since there are potentially many many concrete instances of different collection interfaces, you should provide the serializers with concrete types in order to work properly.

JsonConvert.Deserialize not recognizing array

I'm a little stumped on this one. Everything I do to check this out says it is a valid Json array, but JsonConvert.Deserialize says it is an object. Can someone point out what I'm doing wrong?
Code to replicate:
var data = "[{\"User\": {\"Identifier\": \"24233\",\"DisplayName\": \"Commerce Test Student\",\"EmailAddress\": \"email#email.ca\",\"OrgDefinedId\": \"UniqueId1\",\"ProfileBadgeUrl\": null,\"ProfileIdentifier\": \"zzz123\"},\"Role\": {\"Id\": 153,\"Code\": null,\"Name\": \"Commerce Student\"}}]";
var items = JsonConvert.DeserializeObject<List<T>>(data);
Where T is an object that matches the format below:
public class OrgUnitUser
{
public User User { get; set; }
public RoleInfo Role { get; set; }
}
public class User
{
public string Identifier { get; set; }
public string DisplayName { get; set; }
public string EmailAddress { get; set; }
public string OrgDefinedId { get; set; }
public string ProfileBadgeUrl { get; set; }
public string ProfileIdentifier { get; set; }
}
public class RoleInfo
{
public int Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
It results in an error
Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[CoverPages.Models.D2L.OrgUnitUser]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
Any/all help is appreciated!
var data = "[{\"User\": {\"Identifier\": \"24233\",\"DisplayName\": \"Commerce Test Student\",\"EmailAddress\": \"email#email.ca\",\"OrgDefinedId\": \"UniqueId1\",\"ProfileBadgeUrl\": null,\"ProfileIdentifier\": \"zzz123\"},\"Role\": {\"Id\": 153,\"Code\": null,\"Name\": \"Commerce Student\"}}]";
public class User
{
public string Identifier { get; set; }
public string DisplayName { get; set; }
public string EmailAddress { get; set; }
public string OrgDefinedId { get; set; }
public object ProfileBadgeUrl { get; set; }
public string ProfileIdentifier { get; set; }
}
public class Role
{
public int Id { get; set; }
public object Code { get; set; }
public string Name { get; set; }
}
public class RootObject
{
public User User { get; set; }
public Role Role { get; set; }
}
var items = JsonConvert.DeserializeObject<List<RootObject>>(data);
or
var items = JsonConvert.DeserializeObject<List<RootObject>>(data)[0];
Try this code I thinks he working good
result:
Thanks to Taras for the confirmation, but there is nothing wrong with the code itself.
When using a generic in JsonConver.Deserialize, it gives the error I listed above, however putting in the actual type of OrgUnitUser into the list, rather than T results in the convert succeeding.
Changing the code from
var items = JsonConvert.DeserializeObject<List<T>>(data);
to
var items = JsonConvert.DeserializeObject<List<OrgUnitUser>>(data);
Fixed the issue

C# - JsonSerializer - DataContract runtime error

I call for to consume json rest web service.
My classes are:
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace WFAEsura
{
[DataContract]
class JsonResponse
{
[DataMember]
public string status { get; set; }
[DataMember]
public Result result { get; set; }
}
class Result
{
public string studentStatus { get; set; }
public List<Results> results { get; set; }
}
class Results
{
public string code { get; set; }
public string description { get; set; }
public double creditAmount { get; set; }
public int timeUnit { get; set; }
public string mark { get; set; }
public bool passed { get; set; }
public string staffMemberName { get; set; }
public List<Results> subResults { get; set; }
}
}
For to create these classes I've used
http://json2csharp.com/
My main class is
var syncClient = new WebClient();
string content = syncClient.DownloadString(baseUrl);
// Create the Json serializer and parse the response
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JsonResponse));
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(content)))
{
// deserialize the JSON object
var jsonResponse = (JsonResponse)serializer.ReadObject(ms);
}
But in line jsonResponse = (JsonResponse)serializer.ReadObject(ms)
i've invalidDataContractException WFEsura.Result cann't be seralized.
Description is:
An unhandled exception of type 'System.Runtime.Serialization.InvalidDataContractException' occurred in System.Runtime.Serialization.dll
Additional information: Type 'WFAEsura.Result' cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
In App.config i've
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
What am I doing wrong?
You must mark all classes and properties:
[DataContract]
class JsonResponse
{
[DataMember]
public string status { get; set; }
[DataMember]
public Result result { get; set; }
}
[DtaContract]
class Result
{
[DataMember]
public string studentStatus { get; set; }
[DataMember]
public List<Results> results { get; set; }
}
[DtaContract]
class Results
{
[DataMember]
public string code { get; set; }
[DataMember]
public string description { get; set; }
[DataMember]
public double creditAmount { get; set; }
[DataMember]
public int timeUnit { get; set; }
[DataMember]
public string mark { get; set; }
[DataMember]
public bool passed { get; set; }
[DataMember]
public string staffMemberName { get; set; }
[DataMember]
public List<Results> subResults { get; set; }
}

Categories