Deserialize Json with top Array and first unnamed object - c#

I am consuming an API that returns the following JSON:
[
{
"product": {
"id": 2,
"name": "Auto"
}
}
]
So, I am trying to deserialize this in C# object wihout success.
I'd tried a lot of other's stackoverflow solutions.
Here are my attempt:
public class DomainMessageResponse : BaseResponseMessage
{
public Example data { get; set; }
}
public class Example
{
[JsonProperty("product")]
public Product product { get; set; }
}
public class Product
{
[JsonProperty("id")]
public int id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
}
The problem is that the JSON is beginning with [] and our generic method (that I use from an internal framework) was not able to due with it. I'm getting the following exception:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type....
Thanks #EZI and #eocron for valid solution's.

You should deserialize to array/list. Below code should work...
var list = JsonConvert.DeserializeObject<List<Item>>(json);
public class Product
{
public int id { get; set; }
public string name { get; set; }
}
public class Item
{
public Product product { get; set; }
}

There is two solutions to your problem, considering the way you want to use your object.
First one is to simply create DTO with same fields. Used when you need full control:
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace ConsoleTest
{
class Program
{
[DataContract]
public class Example
{
[DataMember]
public Product Product { get; set; }
}
[DataContract]
public class Product
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
}
static void Main(string[] args)
{
var json = #"
[
{
""product"": {
""id"": 2,
""name"": ""Auto""
}
}
]";
var obj = JsonConvert.DeserializeObject<List<Example>>(json,
new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
}
}
}
The second one used when you want a few fields from json and don't care much about everything else, and uses dynamic type. Easy to code, easy to use, looks pretty good, but not very safe:
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
var json = #"
[
{
""product"": {
""id"": 2,
""name"": ""Auto""
}
}
]";
dynamic list = JsonConvert.DeserializeObject<List<dynamic>>(json);
var id = (int)list[0].product.id;
}
}
}

Related

Trying to deserialize JSON returns null values

Using the method JsonConvert.DeserializeObject returns the default values for all properties.
var current = JsonConvert.DeserializeObject<Current>(myJson);
{
"location": {
"name": "London"
},
"current": {
"temp_c": 5.0,
"cloud": 50
}
}
public class Current
{
public double Temp_c { get; set; }
public double Cloud { get; set; }
}
The expected current object should have the values: 50 for Cloud, and 5.0 for Temp_c, but returns the default values for all properties.
You need to define a class model like json object
and then deserialize to it
public class YourModel {
//create location class that has Name property
public Location Location { get; set; }
//create current class that has Temp_c and Cloud property
public Current Current { get; set; }
}
and then
var data = JsonConvert.DeserializeObject<YourModel>(myJson);
and get the current value from data object
var current = data.Current;
your 'Current' class is far of been like the JSON you post.
You need to convert the JSON string to a C# class. You can use QuickType to convert it (Newtonsoft compatible).
Note: I am using System.Text.Json.Serialization but the class model should be equal, just change:
[JsonPropertyName("temp_c")] // .Net serializer (I prefer this)
to
[JsonProperty("temp_c")] // Newtonsoft.Json serializer
(replace "temp_c" for every name)
Here is the class model (a complete console application) you need:
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
#nullable disable
namespace test
{
public class Weather
{
[JsonPropertyName("location")]
public Location Location { get; set; }
[JsonPropertyName("current")]
public Current Current { get; set; }
}
public class Location
{
[JsonPropertyName("name")]
public string Name { get; set; }
}
public class Current
{
[JsonPropertyName("temp_c")]
public double TempC { get; set; }
[JsonPropertyName("cloud")]
public int Cloud { get; set; }
}
class Program
{
static void Main(string[] args)
{
string json = "{\"location\": { \"name\": \"London\" }, \"current\": { \"temp_c\": 5.0, \"cloud\": 50 }}";
Weather myWeather = JsonSerializer.Deserialize<Weather>(json);
Console.WriteLine("Location: {0} - Temp: {1:F}", myWeather.Location.Name, myWeather.Current.TempC);
}
}
}
Now the Deserializer will work OK.

Skipping parent properly in JsonDeserializer

I am receiving an HttpResponseMessage that looks like this (data redacted):
{
"tracks" : {
"href" : "{href_here}",
"items" : [ {
"album" : {
//stuff here
},
"name": "{name here}"
},
{
"album" : {
//more stuff here
},
"name": "{other name here}"
}
}
}
My model looks like this:
using System.Text.Json.Serialization;
namespace ProjectName.Models
{
public class Track
{
[JsonPropertyName("album")]
public Album Album { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
}
}
I am then attempting to deserialise the response like so:
var response = await _httpClient.GetAsync("URL HERE");
response.EnsureSuccessStatusCode();
return JsonSerializer.Deserialize<IEnumerable<Track>>(await response.Content.ReadAsStringAsync());
I would like to retrieve a list of Tracks (which corresponds to items in JSON).
I cannot find a way online to "skip" parent properties and only deserialize a specific child (in this case items). I do not need href (and the other properties that I have removed).
Is there a way to do this?
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace StackOverflow
{
public class Album
{
}
public class Item
{
[JsonPropertyName("album")]
public Album Album { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
}
public class Tracks
{
[JsonPropertyName("href")]
public string Href { get; set; }
[JsonPropertyName("items")]
public List<Item> Items { get; set; }
}
public class Root
{
[JsonPropertyName("tracks")]
public Tracks Tracks { get; set; }
}
class Program
{
static void Main(string[] args)
{
var jsonStr = "{\"tracks\":{\"href\":\"{href_here}\", \"items\" : [{\"album\" : { }, \"name\": \"{name here}\"}]}}";
var root = JsonSerializer.Deserialize<Root>(jsonStr);
//Here is your "IEnumerable<Track>"
var items = root.Tracks.Items;
}
}
}
Your model must have such a structure, then it deserialize your data as expected. Then you can use Linq to bring the result to every format you want.

Unable to retrieve correct values from the JSON format. Assistance required

I need a little assistance in obtaining values from a JSON object in C#. Here is the code and the output. I am trying to retrieve value of ScoreRepresentation from both the objects. The obtained values in this case would be BR400L and null as per the below output.
Can anyone please assist? Newbie in C# :) Thanks in advance
using System;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Test
{
class Program
{
static void Main(string[] args)
{
var json = "{\"Results\":[{\"RequestIdentifier\":\"Lexile\",\"ValueType\":\"INTEGER\",\"Scores\":[{\"lexile\":{\"ScoreValue\":-400,\"ScaledScore\":-400,\"ScoreRepresentation\":\"BR400L\"}}]},{\"RequestIdentifier\":\"UnifiedScaleScore\",\"ValueType\":\"INTEGER\",\"Scores\":[{\"unifiedScaleScore\":{\"ScoreValue\":610,\"ScaledScore\":610,\"ScoreRepresentation\":null}}]}]}";
var deserialized = JsonConvert.DeserializeObject(json);
Console.WriteLine(deserialized);
}
}
}
Output:
{
"Results": [
{
"RequestIdentifier": "Lexile",
"ValueType": "INTEGER",
"Scores": [
{
"lexile": {
"ScoreValue": -400,
"ScaledScore": -400,
"ScoreRepresentation": "BR400L"
}
}
]
},
{
"RequestIdentifier": "UnifiedScaleScore",
"ValueType": "INTEGER",
"Scores": [
{
"unifiedScaleScore": {
"ScoreValue": 610,
"ScaledScore": 610,
"ScoreRepresentation": null
}
}
]
}
]
}
I like to go the "Model" route. You create models of your data, then you can easily deserialize to them. Sometimes when I am feeling lazy, I will use this site to do my work for me.
So, for your specific example, it gives back these models:
public class Lexile {
public int ScoreValue { get; set; }
public int ScaledScore { get; set; }
public string ScoreRepresentation { get; set; }
}
public class UnifiedScaleScore {
public int ScoreValue { get; set; }
public int ScaledScore { get; set; }
public object ScoreRepresentation { get; set; }
}
public class Score {
public Lexile lexile { get; set; }
public UnifiedScaleScore unifiedScaleScore { get; set; }
}
public class Result {
public string RequestIdentifier { get; set; }
public string ValueType { get; set; }
public List<Score> Scores { get; set; }
}
public class Root {
public List<Result> Results { get; set; }
}
Then, you can simply deserialize to Root by doing this:
var deserialized = JsonConvert.DeserializeObject<Root>(json);
Keep in mind that if your JSON is not perfect, you will find some inconsistencies with the output. You may have to massage your models a bit to fix those issues. You can't just assume that site gives you 100% accurate data.
But, if it's good enough, you can now get at every property you'd ever need to without having to putz around with dynamics or JToken.
For example:
foreach(var r in deserialized.Results)
{
foreach(var s in r.Scores)
{
Console.Write(s.unifiedScaleScore.ScoreRepresentation);
}
}

c# JSON Parcing

Im having trouble in parsin JSON in C#. I want to parse this Json Format.
{
"data":
[
{
"id": 3,
"code": "‎0000004",
}
]
}
Here is my code in C#.
public Data data { get; set; }
public class Data
{
public string id { get; set; }
public string code { get; set; }
}
The JSON shown is an object that has (as data) an array of elements that have an id and code, so:
public class SomeRoot {
public List<Data> data {get;} = new List<Data>();
}
and deserialize a SomeRoot and you should be fine:
var root = JsonConvert.DeserializeObject<SomeRoot>(json);
var obj = root.data[0];
Console.WriteLine(obj.id);
Console.WriteLine(obj.code);
You are missing an essential part, the outer object. Also, the data is an array:
public class RootObject
{
public Data[] data { get; set; }
}
RootObject r = JsonConvert.DeserializeObject<RootObject>(json);
Next time, follow the steps as outlined in Easiest way to parse JSON response. It will help you generate the correct class.
It should be :
public class Data
{
public int id { get; set; }
public string code { get; set; }
}
public class RootObject
{
public List<Data> data { get; set; }
}

C# Parse JSON response (Get a specific part from response)

I am trying to get a specific part from a JSON response string.
Here is the JSON code :
{
"metadata": {
"provider": "Oxford University Press"
},
"results": [
{
"id": "door",
"language": "en",
"lexicalEntries": [
{
"entries": [
{
"homographNumber": "000",
"senses": [
{
"definitions": [
"a hinged, sliding, or revolving barrier at the entrance to a building, room, or vehicle, or in the framework of a cupboard"
],
"id": "m_en_gbus0290920.005",
"subsenses": [
{
"definitions": [
"a doorway"
],
"id": "m_en_gbus0290920.008"
},
{
"definitions": [
"used to refer to the distance from one building in a row to another"
],
"id": "m_en_gbus0290920.009"
}
]
}
]
}
],
"language": "en",
"lexicalCategory": "Noun",
"text": "door"
}
],
"type": "headword",
"word": "door"
}
]
}
I am trying to get this code
"definitions": [
"a hinged, sliding, or revolving barrier at the entrance to a building, room, or vehicle, or in the framework of a cupboard"
in a string
Here is my code:
string language = "en";
string word_id = textBox1.Text.ToLower();
String url = "https://od-api.oxforddictionaries.com:443/api/v1/entries/" + language + "/" + word_id+"/definitions";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Add("app_id", app_Id);
client.DefaultRequestHeaders.Add("app_key", app_Key);
HttpResponseMessage response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
var s = JsonConvert.DeserializeObject(result);
textBox2.Text = s.ToString();
}
else MessageBox.Show(response.ToString());
I am using C#.
C# Classes
Step one is to create some classes to allow us to represent the data in C#. If you don't have them... QuickType does that.
namespace QuickType
{
using System;
using System.Net;
using System.Collections.Generic;
using Newtonsoft.Json;
public partial class GettingStarted
{
[JsonProperty("metadata")]
public Metadata Metadata { get; set; }
[JsonProperty("results")]
public Result[] Results { get; set; }
}
public partial class Result
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("lexicalEntries")]
public LexicalEntry[] LexicalEntries { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("word")]
public string Word { get; set; }
}
public partial class LexicalEntry
{
[JsonProperty("entries")]
public Entry[] Entries { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("lexicalCategory")]
public string LexicalCategory { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
public partial class Entry
{
[JsonProperty("homographNumber")]
public string HomographNumber { get; set; }
[JsonProperty("senses")]
public Sense[] Senses { get; set; }
}
public partial class Sense
{
[JsonProperty("definitions")]
public string[] Definitions { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("subsenses")]
public Subsense[] Subsenses { get; set; }
}
public partial class Subsense
{
[JsonProperty("definitions")]
public string[] Definitions { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
}
public partial class Metadata
{
[JsonProperty("provider")]
public string Provider { get; set; }
}
public partial class GettingStarted
{
public static GettingStarted FromJson(string json) => JsonConvert.DeserializeObject<GettingStarted>(json, Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this GettingStarted self) => JsonConvert.SerializeObject(self, Converter.Settings);
}
public class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
};
}
}
Deserialize
You'll notice that we also have converters to serialize and deserialize generated for us. The deserialize bit is as simple as:
var result = JsonConvert.DeserializeObject<GettingStarted>(json);
Use
Start from the result variable and use dots to find your way down to your item...
var description = result.results.lexicalEntries.First()
.entries.First()
.senses.First()
.definitions.First();
All of those First() calls are due to each of these parts of the data being arrays. You'll need to reference System.Linq for that. You will want to read a little around what to do if you have more than one, or less than one, at any of those levels (you may need to work with collections, or perform more traversal).
You can create a class whose properties are the names of the JSON you are trying to parse. That way you can deserialize the JSON into an instance of that class and pull whatever property you need. You'll need to use the Newtonsoft.Json package.
Example class:
public class YourClass
{
public string propertyA { get; set; }
public string propertyB { get; set; }
}
And then in your main code:
YourClass yourClass = new YourClass();
try
{
yourClass = JsonConvert.DeserializeObject<YourClass>(yourJsonStringGoesHere);
}
catch (Exception ex)
{
//log exception here
}

Categories