C# JSON.NET invalid type - c#

I am curenntly making an thunder storm app for windows phone but i have a problem.
When i have converted the JSON string to C# classes i have seen that the class names just contain numbers.
How can i deserialize the JSON String?
public class 904
{
public string id { get; set; }
public string name { get; set; }
public string name_url { get; set; }
public string region_path { get; set; }
}
public class Result
{
public 904 904 { get; set; }
}
public class RootObject
{
public bool status { get; set; }
public Result result { get; set; }
public int time_valid_to { get; set; }
}
The JSON string
{"status":true,"result":{"904":{"id":"904","name":"Wien Alsergrund","name_url":"wien_alsergrund","region_path":"oesterreich\/wien\/wien_alsergrund"}},"time_valid_to":1424978715}

It looks like the result property is effectively a map of results - so you can represent that with a Dictionary<,>. This works:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
public class ResultEntry
{
public string id { get; set; }
public string name { get; set; }
public string name_url { get; set; }
public string region_path { get; set; }
}
public class RootObject
{
public bool status { get; set; }
public Dictionary<int, ResultEntry> result { get; set; }
public int time_valid_to { get; set; }
}
class Test
{
static void Main()
{
string json = File.ReadAllText("json.txt");
var root = JsonConvert.DeserializeObject<RootObject>(json);
Console.WriteLine(root.result[904].name);
}
}
I'd strongly recommend using cleaner property names and specifying attributes to tell Json.NET how to map them to JSON though.

Related

How to deserialize a string containing multiple JSON [duplicate]

This question already has answers here:
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value
(2 answers)
Closed 7 months ago.
From time to time, my system, through a Timer, executes a procedure that captures a list of events generated by the API, however, when trying to serialize, it returns the following error.
Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: {. Path '[1].metadata', line 1, position 453.'
In this case, this is the string I get from the API.
[{"id":"6ed69e14-6610-4b57-a06f-328f38a9e2aa","code":"PLC","fullCode":"PLACED","orderId":"c6184662-2116-4a66-9f6b-4e6caca59e0d","merchantId":"355d10e6-8825-46e3-81dc-0961bf27a5dc","createdAt":"2022-07-14T12:45:34.142Z"},{"id":"e064302e-6a65-4821-ba4c-ea7021aaf8cc","code":"CAN","fullCode":"CANCELLED","orderId":"c6184662-2116-4a66-9f6b-4e6caca59e0d","merchantId":"355d10e6-8825-46e3-81dc-0961bf27a5dc","createdAt":"2022-07-14T12:53:34.674Z","metadata":{"CANCEL_STAGE":"[PRE_CONFIRMED]","ORIGIN":"IfoodGatewayAgent","CANCEL_CODE":"902","CANCELLATION_DISPUTE":{"IS_CONTESTABLE":"CANCELLATION_IS_NOT_CONTESTABLE","REASON":"NO_CREDIT_FOR_ORDER_LIABILITIES"},"CANCELLATION_OCCURRENCE":{"tags":["NO_CREDIT_FOR_ORDER_LIABILITIES"],"RESTAURANT":{"FINANCIAL_OCCURRENCE":"NA","PAYMENT_TYPE":"NA"},"CONSUMER":{"FINANCIAL_OCCURRENCE":"NA","PAYMENT_TYPE":"NA"},"LOGISTIC":{"FINANCIAL_OCCURRENCE":"NA","PAYMENT_TYPE":"NA"}},"TIMEOUT_EVENT":false,"CANCEL_ORIGIN":"RESTAURANT","CANCEL_REASON":"AUTOMATICO - NAO CONFIRMADO PELO RESTAURANTE","CANCEL_USER":"Order BackOffice Scheduler","CANCELLATION_REQUESTED_EVENT_ID":"17da3940-661e-4d9c-a15a-57f5d1b06474"}}]
This is the part that gives an error in the code:
var data = response.Content.ReadAsStringAsync();
var bodyResponse = JsonConvert.DeserializeObject<List<Classes.OrderStatus>>(await data);
Class OrderStatus:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace SAFI_Delivery.Classes
{
internal class OrderStatus
{
[JsonProperty("id")]
public string ID { get; set; }
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("fullCode")]
public string FullCode { get; set; }
[JsonProperty("orderId")]
public string OrderID { get; set; }
[JsonProperty("merchantId")]
public string MerchantID { get; set; }
[JsonProperty("createdAt")]
public string CreatedAt { get; set; }
[JsonProperty("metadata")]
public string Metadata { get; set; }
}
}
I would like to know how I make it consider that this is a list and not a string?
you have to fix classes and code
var json= await response.Content.ReadAsStringAsync();
var bodyResponse = JsonConvert.DeserializeObject<List<OrderStatus>>(json);
classes
public partial class OrderStatus
{
[JsonProperty("id")]
public Guid Id { get; set; }
[JsonProperty("code")]
public string Code { get; set; }
[JsonProperty("fullCode")]
public string FullCode { get; set; }
[JsonProperty("orderId")]
public Guid OrderId { get; set; }
[JsonProperty("merchantId")]
public Guid MerchantId { get; set; }
[JsonProperty("createdAt")]
public DateTimeOffset CreatedAt { get; set; }
[JsonProperty("metadata", NullValueHandling = NullValueHandling.Ignore)]
public Metadata Metadata { get; set; }
}
public partial class Metadata
{
[JsonProperty("CANCEL_STAGE")]
public string CancelStage { get; set; }
[JsonProperty("ORIGIN")]
public string Origin { get; set; }
[JsonProperty("CANCEL_CODE")]
public long CancelCode { get; set; }
[JsonProperty("CANCELLATION_DISPUTE")]
public CancellationDispute CancellationDispute { get; set; }
[JsonProperty("CANCELLATION_OCCURRENCE")]
public CancellationOccurrence CancellationOccurrence { get; set; }
[JsonProperty("TIMEOUT_EVENT")]
public bool TimeoutEvent { get; set; }
[JsonProperty("CANCEL_ORIGIN")]
public string CancelOrigin { get; set; }
[JsonProperty("CANCEL_REASON")]
public string CancelReason { get; set; }
[JsonProperty("CANCEL_USER")]
public string CancelUser { get; set; }
[JsonProperty("CANCELLATION_REQUESTED_EVENT_ID")]
public Guid CancellationRequestedEventId { get; set; }
}
public partial class CancellationDispute
{
[JsonProperty("IS_CONTESTABLE")]
public string IsContestable { get; set; }
[JsonProperty("REASON")]
public string Reason { get; set; }
}
public partial class CancellationOccurrence
{
[JsonProperty("tags")]
public List<string> Tags { get; set; }
[JsonProperty("RESTAURANT")]
public Consumer Restaurant { get; set; }
[JsonProperty("CONSUMER")]
public Consumer Consumer { get; set; }
[JsonProperty("LOGISTIC")]
public Consumer Logistic { get; set; }
}
public partial class Consumer
{
[JsonProperty("FINANCIAL_OCCURRENCE")]
public string FinancialOccurrence { get; set; }
[JsonProperty("PAYMENT_TYPE")]
public string PaymentType { get; set; }
}
Answered Question.
Thanks, Drew
I'm not too familiar with the JSON library you're using, but I suspect the issue is that, in your OrderStatus class, you have the Metadata property as a string type, but in your example JSON, the "metadata" key has an object value, not a string value.

How to parse JSON data having dot(.) operator? [duplicate]

This question already has answers here:
Deserialize JSON with dot in property name
(2 answers)
Closed 2 years ago.
I have a JSON response like below:
{
"sitePropertiesMap":
{
"site.web.url.protocol":
{
"sitePropertyId": 2497,
"siteId": 66,
"key": "site.web.url.protocol",
"value": "https",
"type": null,
"globalAdminOnly": "disabled",
"hideDefaultValue": "disabled"
}
}
}
How can I access the "sitePropertyId" value from this? I tried to create a modal class like below:
public class sitePropertiesMap
{
public class site.web.url.protocol
{
public string sitePropertyId { get; set; }
}
}
But getting an error because the class name having a dot operator(.)
Error Screenshot:
In this case, how can I parse the JSON value?
You can use the JsonProperty attribute of JSON.NET
public class Rootobject
{
public Sitepropertiesmap sitePropertiesMap { get; set; }
}
public class Sitepropertiesmap
{
[JsonProperty(PropertyName = "site.web.url.protocol")]
public SiteWebUrlProtocol siteweburlprotocol { get; set; }
}
public class SiteWebUrlProtocol
{
public int sitePropertyId { get; set; }
public int siteId { get; set; }
public string key { get; set; }
public string value { get; set; }
public object type { get; set; }
public string globalAdminOnly { get; set; }
public string hideDefaultValue { get; set; }
}
And then deserialize like this:
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Rootobject>(json);
You need to use using Newtonsoft.Json; to use this.
You can use a dictionary
public class RootObject
{
public Dictionary<string,SiteProperties> SitePropertiesMap { get; set; }
}
public class SiteProperties
{
public int SitePropertyId { get; set; }
public int SiteId { get; set; }
public string Key { get; set; }
public string Value { get; set; }
public string GlobalAdminOnly { get; set; }
public string HideDefaultValue { get; set; }
}
and access the value like
obj.SitePropertiesMap["site.web.url.protocol"].SitePropertyId
.net fiddle example
One approach is to use Newtonsoft's PropertyName attribute and remove the dots inside the property's name of your model class.
https://dotnetfiddle.net/uFnHEK
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var json = "{\"sitePropertiesMap\": { \"site.web.url.protocol\": { \"sitePropertyId\": 2497, \"siteId\": 66, \"key\": \"site.web.url.protocol\", \"value\": \"https\", \"type\": null, \"globalAdminOnly\": \"disabled\", \"hideDefaultValue\": \"disabled\" } } }";
var obj = JsonConvert.DeserializeObject<RootObject>(json);
Console.WriteLine(obj.sitePropertiesMap.SiteWebUrlProtocol.sitePropertyId);
}
}
public class SiteWebUrlProtocol
{
public int sitePropertyId { get; set; }
public int siteId { get; set; }
public string key { get; set; }
public string value { get; set; }
public object type { get; set; }
public string globalAdminOnly { get; set; }
public string hideDefaultValue { get; set; }
}
public class SitePropertiesMap
{
[JsonProperty(PropertyName = "site.web.url.protocol")]
public SiteWebUrlProtocol SiteWebUrlProtocol { get; set; }
}
public class RootObject
{
public SitePropertiesMap sitePropertiesMap { get; set; }
}

Geocoding REST call C# Parsing JSON

I'm struggling to pick up the data returned from the Geocoding REST call below (I've removed my app_id and app_code so you cannot run the url as it is below):
https://geocoder.api.here.com/6.2/geocode.json?app_id=[MY APP ID]&app_code=[MY APP CODE]&searchtext=chester
An example reponse can be found here:
https://developer.here.com/documentation/geocoder/topics/quick-start-geocode.html
I know it returns results but I cannot seem to get the results through to my C# application, I don't know if I'm building the class system incorrectly or whether there's something else I'm doing wrong. I've built an application reading the places api with no problem before but this one seems different somehow.
The call returns with a status of OK:
public void GeoCode()
{
// BUILD INITIAL STRING BASED ON PARAMETERS
string url = "https://geocoder.api.here.com/6.2/geocode.json?app_id=gpZ1Ym7rwuXs6Xj1TsD8&app_code=4UXmaGFTe30LttFgOY7iqQ&searchtext=" + tbLoc.text;
// RUN THE ASYNCRONOUS COMMAND (I THINK)
StartCoroutine(GetText(url));
}
IEnumerator GetText(string url)
{
// CREATE WEB REQUEST WITH SPECIFIED URL
UnityWebRequest www = UnityWebRequest.Get(url);
// RETURN RESULTS FROM ASYNC COMMAND
yield return www.SendWebRequest();
// PARSE JSON RESPONSE
RootObject RootObject = JsonUtility.FromJson<RootObject>(www.downloadHandler.text);
// IF 200 (STATUS OKAY) GATHER RESULTS, ELSE RETURN ERROR
if (www.responseCode == 200)
{
BuildArray(RootObject);
}
else
{
Debug.Log("Call Failed With Error: " + www.responseCode.ToString());
}
}
private void BuildArray(RootObject RootObject)
{
print(RootObject.Response.View[0].Result[0].Location.Address.Label);
}
It attempts to run the BuildArray function but this returns a null reference. (I'm just using the NextPageInformation as the most basic option to test)
Below is the class structure I have built to deal with the JSON:
public class Address
{
public string Label { get; set; }
}
public class Location
{
public Address Address { get; set; }
}
public class Result
{
public Location Location { get; set; }
}
public class View
{
public List<Result> Result { get; set; }
}
public class Response
{
public List<View> View { get; set; }
}
public class RootObject
{
public Response Response { get; set; }
}
Can someone please help?
Thank you
If you want to parse only one key value pair from json then creating class structure will tedious job for you.
Instead of creating class structure you can Querying a json with Newtonsoft.
Parse your json.
Querying your parsed json to retrieve Label
value.
//1
JToken jToken = JToken.Parse(jsonString);
//2
string label = jToken["Response"]["View"][0]["Result"][0]["Location"]["Address"]["Label"].ToObject<string>();
Console.WriteLine(label);
Console.ReadLine();
Output: (from your sample json provided in link)
Note: You need to install newtonsoft.json package from nuget and add below namespace to your program.
using Newtonsoft.Json.Linq;
Edit:
If you want parsed your full json then first create a class structure like below
public class MetaInfo
{
public DateTime Timestamp { get; set; }
}
public class MatchQuality
{
public int City { get; set; }
public List<double> Street { get; set; }
public int HouseNumber { get; set; }
}
public class DisplayPosition
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class NavigationPosition
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class TopLeft
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class BottomRight
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class MapView
{
public TopLeft TopLeft { get; set; }
public BottomRight BottomRight { get; set; }
}
public class AdditionalData
{
public string value { get; set; }
public string key { get; set; }
}
public class Address
{
public string Label { get; set; }
public string Country { get; set; }
public string State { get; set; }
public string County { get; set; }
public string City { get; set; }
public string District { get; set; }
public string Street { get; set; }
public string HouseNumber { get; set; }
public string PostalCode { get; set; }
public List<AdditionalData> AdditionalData { get; set; }
}
public class Location
{
public string LocationId { get; set; }
public string LocationType { get; set; }
public DisplayPosition DisplayPosition { get; set; }
public List<NavigationPosition> NavigationPosition { get; set; }
public MapView MapView { get; set; }
public Address Address { get; set; }
}
public class Result
{
public int Relevance { get; set; }
public string MatchLevel { get; set; }
public MatchQuality MatchQuality { get; set; }
public string MatchType { get; set; }
public Location Location { get; set; }
}
public class View
{
public string _type { get; set; }
public int ViewId { get; set; }
public List<Result> Result { get; set; }
}
public class Response
{
public MetaInfo MetaInfo { get; set; }
public List<View> View { get; set; }
}
public class RootObject
{
public Response Response { get; set; }
}
And then you can deserialized your json like.
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(jsonString);
Note: You need to add below namespace to your program.
using Newtonsoft.Json;
I personally had problems parsing nested json objects with JsonUtility. So I switched to Newtonsoft Json and it works really well.
In your case you need to mark the classes as serialized using [Serializable] see here
[Serializable]
public class Address
{
public string Label;
}

Deserializing list of items

I have following sample Json string:
{"Items":[{"Id":"20","CaptureCategoryTypeId":5021,"Name":"24270","Description":"FSH CARRIBEAN CAPTAIN","IsEnabled":true}],"TotalResults":0}
I need to deserialize the same but I don't want to keep my class name as following:
public class Item
{
public string Id { get; set; }
public int CaptureCategoryTypeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsEnabled { get; set; }
}
public class RootObject
{
public List<Item> Items { get; set; }
public int TotalResults { get; set; }
}
I want to keep custom class name such DataDetails. How that can be achieved in c#?
I don't quite understand what your question is but you can just change the class names to whatever you want. Below is a working example.
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string JSONInput = #"{""Items"":[{""Id"":""20"",""CaptureCategoryTypeId"":5021,""Name"":""24270"",""Description"":""FSH CARRIBEAN CAPTAIN"",""IsEnabled"":true}],""TotalResults"":0}";
BlahObject deserializedProduct = JsonConvert.DeserializeObject<BlahObject>(JSONInput);
Console.ReadKey();
}
}
public class DataDetails
{
public string Id { get; set; }
public int CaptureCategoryTypeId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public bool IsEnabled { get; set; }
}
public class BlahObject
{
public List<DataDetails> Items { get; set; }
public int TotalResults { get; set; }
}
}

Custom JSON, convert to object

I have the result of an API call which looks like:
{"Operations":[{"OperationId":"2","OperationObjectId":"Application","OperationName":"UnlockSession","OperationParameters":[{"Name":"viewModel","Value":"model"},{"Name":"returnUrl","Value":"https://"}],"OperationCaller":{"UserPrincipalName":"bob","ClientIPAddress":""},"OperationResult":"Succeeded","OperationStatus":200,"OperationRequest":{"Method":"POST","Url":""},"OperationStartedTime":"2013-08-20T12:04:17.5462357Z","OperationCompletedTime":"2013-08-20T12:04:17.9979469Z"}],"ContinuationToken":null}
Ideally I want to convert it to an object so I can do stuff like:
object.OperationObjectID; // gives Application
object.Method; // gives POST
object.OperationResult; // gives Succeeded
Does any one know how that is done? Does the JSON parse need to be aware of the format?
Thanks,
Andrew
you can use Json.Net as below
dynamic object = JObject.Parse(yorjsonstring);
object.Operations[0].OperationObjectID;
object.Operations[0].Method;
object.Operations[0].OperationResult;
rather than using dynamic object you can generate classes for your json and serialize to those classes like below.
you can get help of http://json2csharp.com/ site for generate classes
public class OperationParameter
{
public string Name { get; set; }
public string Value { get; set; }
}
public class OperationCaller
{
public string UserPrincipalName { get; set; }
public string ClientIPAddress { get; set; }
}
public class OperationRequest
{
public string Method { get; set; }
public string Url { get; set; }
}
public class Operation
{
public string OperationId { get; set; }
public string OperationObjectId { get; set; }
public string OperationName { get; set; }
public List<OperationParameter> OperationParameters { get; set; }
public OperationCaller OperationCaller { get; set; }
public string OperationResult { get; set; }
public int OperationStatus { get; set; }
public OperationRequest OperationRequest { get; set; }
public string OperationStartedTime { get; set; }
public string OperationCompletedTime { get; set; }
}
public class RootObject
{
public List<Operation> Operations { get; set; }
public object ContinuationToken { get; set; }
}
then
RootObject obj = JsonConvert.DeserializeObject<RootObject>(jsonstring);
obj.Operations[0].OperationObjectID;
Try to use JavaScriptSerializer class: http://msdn.microsoft.com/ru-ru/library/system.web.script.serialization.javascriptserializer.aspx.

Categories

Resources