Strange JSON Deserialization c# - c#

I'm having troubles with some Deserialization because I'm not receiving an object like I'm used to but an array. Lets to the code, how I've being doing it:
JSON received:
[{"gcm_regID":"fsdf2156fw62f1wfwe512g"}]
Deserialization
var result = JsonConvert.DeserializeObject<Gcm>(response);
Handlers Tried:
public class Gcm
{
public List<Gcm_reg> gcm_regID { get; set; }
}
public class Gcm_reg
{
public string gcm_regID { get; set; }
}
I've tried just the Gcm_reg as well and nothing seems to work. How can I deserialize this? By the way, I'm using the newsoft JSON.
Best regards,

IEnumerable<Gcm_reg> result = JsonConvert.DeserializeObject<IEnumerable<Gcm_reg>>(response);
You can deserialize the object as an array or IEnumerable

Object should be like
public class Gcm
{
public string gcm_regID { get; set; }
}
So Try it
var result = JsonConvert.DeserializeObject<IEnumerable<Gcm>>(response);
You can directly generate classes from Json by using link
To create same type of object
var outputList = new List<Gcm>();
//loop through this part based on number of input
var itemToAdd = new Gcm();
itemToAdd .regID = 'something';
outputList.Add(itemToAdd );
and send outputList to server.

Related

How to fix error Cannot deserialize the current JSON object? [duplicate]

Below is a (slightly) stripped down response I get from a REST API upon successful creation of a new "job code" entry. I need to deserialize the response into some classes, but I'm stumped.
For reference, I'm using JSON.NET in .NET 3.5 (running in a SSIS script in SQL Server 2008 R2) to attempt my deserialization. Here's the JSON - which I obviously have no control over as it's coming from someone else's API:
{
"results":{
"jobcodes":{
"1":{
"_status_code":200,
"_status_message":"Created",
"id":444444444,
"assigned_to_all":false,
"billable":true,
"active":true,
"type":"regular",
"name":"1234 Main Street - Jackson"
},
"2":{
"_status_code":200,
"_status_message":"Created",
"id":1234567890,
"assigned_to_all":false,
"billable":true,
"active":true,
"type":"regular",
"name":"4321 Some Other Street - Jackson"
}
}
}
}
In my C# code, I do have a "JobCode" class defined which only partially maps the JSON values to properties - I'm not interested in all of the data that's returned to me:
[JsonObject]
class JobCode
{
[JsonProperty("_status_code")]
public string StatusCode { get; set; }
[JsonProperty("_status_message")]
public string StatusMessage { get; set; }
[JsonProperty("id")]
public string Id {get; set;}
[JsonProperty("name")]
public string Name { get; set; }
//-------------------------------------------------------------------------------
// Empty constructor for JSON serialization support
//-------------------------------------------------------------------------------
public JobCode() { }
}
I'm attempting to deserialize the data via this call:
newResource = JsonConvert.DeserializeObject<JobCode>(jsonResponse);
Where jsonResponse is the code outputted above.
When I execute the code, "newResource" always comes back as null - which is not unexpected because I know that there are actually multiple jobcodes in the data and this code is trying to deserialize it into a single JobCode object. I tried creating a new class called "JobCodes" that looks like this:
class JobCodes
{
[JsonProperty("jobcodes")]
public List<JobCode>_JobCodes { get; set; }
}
And then I tried calling this:
newResource = JsonConvert.DeserializeObject<JobCodes>(jsonResponse);
But the issue persists - my return object is null.
What's throwing me off, I think, is the presence of the "1" and "2" identifiers. I don't know how to account for their presence in my object design and/or usage of the JSON.NET class / property attributes like [JsonObject],[JsonProperty], etc.
When I run the JSON data through JSON2CSharp, it constructs some weird-looking classes, so that hasn't proven too effective. I've validated the JSON with several different validators and it all checks out - I just don't know what I'm missing here.
Ultimately, I'd like to return a List from the JSON data, but I'm stumped on what I need to do to make that happen.
Your problem is twofold:
You don't have a class defined at the root level. The class structure needs to match the entire JSON, you can't just deserialize from the middle.
Whenever you have an object whose keys can change, you need to use a Dictionary<string, T>. A regular class won't work for that; neither will a List<T>.
Make your classes like this:
class RootObject
{
[JsonProperty("results")]
public Results Results { get; set; }
}
class Results
{
[JsonProperty("jobcodes")]
public Dictionary<string, JobCode> JobCodes { get; set; }
}
class JobCode
{
[JsonProperty("_status_code")]
public string StatusCode { get; set; }
[JsonProperty("_status_message")]
public string StatusMessage { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
Then, deserialize like this:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Working demo here
Excellent Answers!
For those out there that may need some more help with the JSON Class Configuration, try: http://json2csharp.com/#
An excellent way of Auto Generating the Classes!
Or even easier, in VS, Goto:
Edit -> Paste Special -> Paste as JSON Classes
Because you can't change the scheme of JSON, and you can't set constant No. of properties, I'd suggest you to use JObject
var jobject = JObject.Parse(json);
var results = jobject["results"];
var jobcodes = results["jobcodes"];
var output = jobcodes.Children<JProperty>()
.Select(prop => prop.Value.ToObject<JobCode>())
.ToList();
Warning: code assumes, that JSON is always in proper schema. You should also handle invalid schema (for example where property is not of JobCode scheme).
You can also deserialize your json to an object of your target class, and then read its properties as per normal:
var obj = DeSerializeFromStrToObj<ClassToSerialize>(jsonStr);
Console.WriteLine($"Property: {obj.Property}");
where DeSerializeFromStrToObj is a custom class that makes use of reflection to instantiate an object of a targeted class:
public static T DeSerializeFromStrToObj<T>(string json)
{
try
{
var o = (T)Activator.CreateInstance(typeof(T));
try
{
var jsonDict = JsonSerializer.Deserialize<Dictionary<string, string>>(json);
var props = o.GetType().GetProperties();
if (props == null || props.Length == 0)
{
Debug.WriteLine($"Error: properties from target class '{typeof(T)}' could not be read using reflection");
return default;
}
if (jsonDict.Count != props.Length)
{
Debug.WriteLine($"Error: number of json lines ({jsonDict.Count}) should be the same as number of properties ({props.Length})of our class '{typeof(T)}'");
return default;
}
foreach (var prop in props)
{
if (prop == null)
{
Debug.WriteLine($"Error: there was a prop='null' in our target class '{typeof(T)}'");
return default;
}
if (!jsonDict.ContainsKey(prop.Name))
{
Debug.WriteLine($"Error: jsonStr does not refer to target class '{typeof(T)}'");
return default;
}
var value = jsonDict[prop.Name];
Type t = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
object safeValue = value ?? Convert.ChangeType(value, t);
prop.SetValue(o, safeValue, null); // initialize property
}
return o;
}
catch (Exception e2)
{
Debug.WriteLine(e2.Message);
return o;
}
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
return default;
}
}
A complete working example class can be found in my enhanced answer to a similar question, here

How can I add json data to a label in C#? ( windows forms )

so i want to get bitcoin price from a URL and see it in a label in my form.
URL
i tried to make a class for it with the code
public string price { get; set; }
but i don't know what to do after that, i searched a lot in google but they all show the result in list and etc
To deserialize, first you need to make a class with the attributes the JSON has. This page will help you a lot in that.
Once you have a class, you need to deserialize your JSON into that class. In C# I like to use JsonConvert from the library Newtonsoft.Json, you need to import it.
The method that deserializes it is JsonConvert.DeserializeObject.
One little example, let's say your class is called Bitcoin, then you would have to do it that way :
var myBitcoin = JsonConvert.DeserializeObject<Bitcoin>(yourJson);
EDIT: To pull your json from an URL you can use Webclient DownloadString method.
var myjson = new WebClient().DownloadString("url");
This post may also help you.
This should be your class.
public class APIResponse
{
public string symbol { get; set; }
public string price { get; set; }
}
Then in your function add these lines.
APIResponse response = new APIResponse();
response = JsonConvert.DeserializeObject<APIResponse>();
myPriceLabel.Text = response.price;
What did we do? We created a C# model same as the Json Data model and we took JSON data and converted it to APIResponse type so we can access it and use it as we like.
It can be achieved simply by converting the Json with generic object
var myBitcoin = JsonConvert.DeserializeObject<object>(yourJson);
thank you all for answering but i found the solution!
the code should be like this
string url = "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT";
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString(url);
JavaScriptSerializer oJS = new JavaScriptSerializer();
PriceClass obj = new PriceClass();
obj = oJS.Deserialize<PriceClass>(json);
BTCPrice_Label.Text = obj.price;
}
and the class should be like this
using System;
public class PriceClass
{
public string symbol { get; set; }
public string price { get; set; }
}

How to convert a JSON string to PSObject?

I want to write a PowerShell function in C#. During the process I receive a string with JSON content.
My sample json content is:
string json = "{'TestNr':{'Name':'CSHARP', 'Description':'Test Descriptiopn'}}"
This string should be converted to a PSObject just like ConvertFrom-Json would do.
I was trying to create an object with below lines. It works but it would require a lot of manual scripting especially if the JSON string becomes longer.
PSObject obj = new PSObject();
obj.Properties.Add(new PSNoteProperty("Head", "Children"));
I tried also the below line:
obj = (PSObject)TypeDescriptor.GetConverter(typeof(PSObject)).ConvertFromString(json);
For this I get however the error (I run the function in PowerShell 7):
TypeConverter cannot convert from System.String.
There are two ways you can parse the string in C# that would be the easiest to go with.
public class MyClass
{
public TestNRClass TestNR { get; set; }
}
public class TestNRClass
{
public string Name { get; set; }
public string Description { get; set; }
}
// In the main,
string json = #"{""TestNr"":{""Name"":""CSHARP"", ""Description"":""Test Descriptiopn""}}";
MyClass jobj = JsonConvert.DeserializeObject<MyClass>(json);
Console.WriteLine(jobj.TestNR.Name);
This is with the strong typed class object. This is what you should be using in C#.
Other way is to get an object
string json = #"{""TestNr"":{""Name"":""CSHARP"", ""Description"":""Test Descriptiopn""}}";
JObject obj = JObject.Parse(json);
Console.WriteLine(obj.ToString());
Console.WriteLine(obj["TestNr"]["Name"].ToString());
// You can also add more keyValuePair
obj["NewVariable"] = "stest";
Console.WriteLine(obj.ToString()); // Shows the new item as well.

Separating array and element from a JSON string

I am connecting you Google Places API to retrive results in the form of a JSON string. You can view the complete format of the string Here.
If you a look at it you will see that the actual results array starts after two elements which are html_attributions and next_page_token.
So When i try to deserialize it in this way:
var serializer = new JavaScriptSerializer();
var arr= serializer.Deserialize(result,typeof(string[]));
I get an empty array.
My question is how is there a way i can separate html_attributions and next_page_token fields and the pass the valid results array from the string to be deserialized?
I don't understand the part where you wish to seperate the html_attributions and the next_page_token.
Wouldn't it be sufficient to just deserialize the response with whatever properties that you need?
For example, you can deserialize the response to only retrieve the values that you desire;
// I represent the wrapper result
class Result
{
public List<string> html_attributions { get; set; }
public string next_page_token { get; set; }
public List<ResultItem> results { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
}
// the actual deserialization
Result Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize(json, typeof(Result));
}
Edit:
The reason that your deserialization doesn't return you a array of strings is because the response that you retrieve is infact an object and not an array, however the parameter within that object which is named results is an array. In order for you to deserialize more properties you'll have to define them in your "ResultItem" class, sorry for my poor naming here.
For instance, if you'd wish to also retrieve the icon property per result you'll have to add a property named "icon" of type string.
Meanwhile the property "photos" is an array, in order to deserialize it you'll have to create another class and add a property of type list/array of that newly created class, and it has to be named "photos" unless you use a different serializer or use DataContract and DataMember attributes (using the Name property for field mapping).
// the representation of a photo within a result item
class Photo
{
public int height { get; set; }
public List<string> html_attributions { get; set; }
public string photo_reference { get; set; }
public int width { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
// the added icon
public string icon { get; set; }
// the added photos collection, could also be an array
public List<Photo> photos { get; set; }
}
Just look at the JSON result to figure out what other properties that you might want to add, for instance the "scope" property is an string whilst the "price_level" is an integer.
If I understand your comment correctly you're only interested in the actual results, you'll still have to deserialize the response correctly with its wrapper.
// the actual deserialization
List<ResultItem> Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize(json, typeof(Result));
return result.results;
}
Edit2:
If you really want a string[] as a result you could simply take use of System.Linq using the code above.
string[] stringArray = result.results.Select(r => string.Format("id:{0} - name:{1}", r.id, r.name)).ToArray();
Edit3:
Instead of using the JavascriptSerializer you could use JObject functionality which can be found in the Newtonsoft.Json.Linq library.
var jsonObject = JObject.Parse(json);
string[] results = jsonObject.SelectTokens("results").Select(r => r.ToString()).ToArray();
This will give you an array of strings where each value within the array is the actual json string for each result.
If you however would like to query for the coordinates only:
var jsonObject = JObject.Parse(json);
var coordinates = jsonObject["results"]
.Select(x => x.SelectToken("geometry").SelectToken("location"))
.Select(x => string.Format("{0},{1}", (string)x.SelectToken("lat"), (string)x.SelectToken("lng")))
.ToArray();
This would give you an array of coordinates, eg:
[
"-33.867217,151.195939",
"-33.866786,151.195633",
...
]
Whatever approach you choose you'll be able to accomplish same results using either Newtonsoft or the .net serializer, whilst the Newtonsoft approach would allow you to query without creating strong types for deserialization.
I don't find the point of "[...] pass the valid results array from the string to be deserialized".
Maybe you need to switch to JSON.NET and do something like this:
// You simply deserialize the entire response to an ExpandoObject
// so you don't need a concrete type to deserialize the whole response...
dynamic responseEntity = JsonConvert.DeserializeObject<ExpandoObject>(
googlePlacesJson, new ExpandoObjectConverter()
);
// Now you can access result array as an `IEnumerable<dynamic>`...
IEnumerable<dynamic> results = responseEntity.results;
foreach(dynamic result in results)
{
// Do stuff for each result in the whole response...
}

C# How to know which element is root object for deserialization?

I used json2csharp to get this:
http://pastebin.com/pbDYCrWk
From that, I wish to get the title that is held in the Oembed section.
I'm using this code:
string url = "http://www.reddit.com/r/all.json";
string jsonText = await DoStuff(url);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonText);
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Page.Oembed>(json);
string test = deserializeObject.title;
And I assumed it would work, however on the line with the deserializeObject variable, I get an error saying it can't do it.
I tried using Page.RootObject however it doesn't work either, and I assumed it would since it seems to be the root.
What am I doing wrong and how can I solve it? Thanks.
If you used Json2CSharp then it is RootObject:
public class RootObject
{
public string kind { get; set; }
public Data data { get; set; }
}
Should be:
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<JuicyReddit.RootObject>(json);

Categories

Resources