Deserialize nested JSON into C# objects
For "Items"
use a Dictionary<string, List<Info>>
, i.e.:
class Response
{
public Dictionary<string, List<Info>> Items { get; set; }
public string[] Errors { get; set; }
}
class Info
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
public int Prop3 { get; set; }
public bool Prop4 { get; set; }
}
This assumes that the item names "Item322A"
and "Item2B"
will vary from response to response, and reads these names in as the dictionary keys.
Sample fiddle.
Deserialize nested JSON, C#
There are a couple of problems here:
In your
Body
class, theTrackList
property does not match the JSON. The corresponding property in the JSON is calledtrack_list
. The class properties must either exactly match the JSON (ignoring case) or else you need to use a[JsonProperty]
attribute on the property to indicate what the JSON name will be. For example:public class Body
{
[JsonProperty("track_list")]
public List<TrackList> TrackList { get; set; }
}You are attempting to deserialize into the
Track
class, but you should be deserializing toRoot
since that represents the root of the JSON.var root = JsonConvert.DeserializeObject<Root>(json);
Once you have deserialized to
Root
you can "drill down" to print out the tracks.foreach (var item in root.message.body.TrackList)
{
Console.WriteLine(item.track.track_name);
}
Fiddle: https://dotnetfiddle.net/JnljGU
Deserialize nested Json into a list
A simple approach is to use JArray
and iterate through the values in the DOM, extracting them as needed:
var parsed = JArray.Parse(json);
foreach (var item in parsed[0]["data"])
{
Console.WriteLine($"{item["lat"]} {item["lng"]} {item["fixTime"]}");
}
However, a more robust method is to deserialize into classes. I just pasted your json into https://json2csharp.com. It even suggests how to deserialize your json (although, since the json represents an array I had to update to deserialize to List<Root>
). This is the result (comments are mine):
// use this to deserialize
List<Root> myDeserializedClass = JsonConvert.DeserializeObject<List<Root>>(myJsonResponse);
// classes
// you'll need to define what goes here
public class Geozones
{
}
public class Datum
{
public string state { get; set; }
public double lat { get; set; }
public double lng { get; set; }
public int accuracy { get; set; }
public int fixTime { get; set; }
public string source { get; set; }
public Geozones geozones { get; set; }
public string address { get; set; }
public string type { get; set; }
public int id { get; set; }
public DateTime time { get; set; }
public DateTime insertTime { get; set; }
public int seqNbr { get; set; }
}
public class Root
{
public List<Datum> data { get; set; }
public bool truncated { get; set; }
public bool skipped { get; set; }
public string serial { get; set; }
public string name { get; set; }
public string type { get; set; }
}
Then to get the values:
foreach (var item in myDeserializedClass)
{
foreach (var data in item.data)
{
Console.WriteLine($"{data.lat} {data.lng} {data.fixTime}");
}
}
Alternatively, you could mix the two approaches and use ToObject<T>()
:
List<Datum> items = JArray.Parse(json)[0]["data"].ToObject<List<Datum>>();
How to deserialize nested JSON in C#
All code was tested using VS2019 and working properly.
The simpliest way will be
var root =Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var path = root + @"\SubtitleTranslator\LanguagesList.json";
var json = File.ReadAllText(path);
var jsonDeserialized = JsonConvert.DeserializeObject<Root>(json);
List<Language> languages = null;
if( jsonDeserialized.StatusCode== 200) languages=jsonDeserialized.Result.languages;
or if you don't need any data except languages, try this code
var languages= JObject.Parse(json)["Result"]["languages"].ToObject<Language[]>();
in this case you will need only Language class
OUTPUT (in both cases)
[{"language":"af","language_name":"Afrikaans","native_language_name":"Afrikaans","country_code":"ZA","words_separated":true,"direction":"left_to_right","supported_as_source":false,"supported_as_target":false,"identifiable":true},
{"language":"ar","language_name":"Arabic","native_language_name":"العربية","country_code":"AR","words_separated":true,"direction":"right_to_left","supported_as_source":true,"supported_as_target":true,"identifiable":true},
{"language":"az","language_name":"Azerbaijani","native_language_name":"آذربایجان دیلی","country_code":"AZ","words_separated":true,"direction":"right_to_left","supported_as_source":false,"supported_as_target":false,"identifiable":true}]
Update
you can test it using Console.WriteLine
foreach (var lg in languages)
{
Console.WriteLine($"Language Name: {lg.native_language_name}, Coutry Code: {lg.country_code}");
}
Language class
public class Language
{
public string language { get; set; }
public string language_name { get; set; }
public string native_language_name { get; set; }
public string country_code { get; set; }
public bool words_separated { get; set; }
public string direction { get; set; }
public bool supported_as_source { get; set; }
public bool supported_as_target { get; set; }
public bool identifiable { get; set; }
}
another classes (if needed)
public class Root
{
public int StatusCode { get; set; }
public Headers Headers { get; set; }
public Result Result { get; set; }
}
public class Headers
{
[JsonProperty("X-XSS-Protection")]
public string XXSSProtection { get; set; }
[JsonProperty("X-Content-Type-Options")]
public string XContentTypeOptions { get; set; }
[JsonProperty("Content-Security-Policy")]
public string ContentSecurityPolicy { get; set; }
[JsonProperty("Cache-Control")]
public string CacheControl { get; set; }
public string Pragma { get; set; }
[JsonProperty("Strict-Transport-Security")]
public string StrictTransportSecurity { get; set; }
[JsonProperty("x-dp-watson-tran-id")]
public string XDpWatsonTranId { get; set; }
[JsonProperty("X-Request-ID")]
public string XRequestID { get; set; }
[JsonProperty("x-global-transaction-id")]
public string XGlobalTransactionId { get; set; }
public string Server { get; set; }
[JsonProperty("X-EdgeConnect-MidMile-RTT")]
public string XEdgeConnectMidMileRTT { get; set; }
[JsonProperty("X-EdgeConnect-Origin-MEX-Latency")]
public string XEdgeConnectOriginMEXLatency { get; set; }
public string Date { get; set; }
public string Connection { get; set; }
}
public class Result
{
public List<Language> languages { get; set; }
}
````
How do I deserialize a nested JSON object which is a string in System.Text.Json?
You need to create a custom JsonConverter<T>
, where T
is EstoData
in this case, to be able to correctly deserialise the nested Data
JSON object.
This should work, both for deserialisation and serialisation of the object again:
StringToEstoDataConverter.cs
public class StringToEstoDataConverter : JsonConverter<EstoData>
{
public override EstoData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
var infoData = jsonDoc.RootElement.GetString();
if (infoData != null)
return JsonSerializer.Deserialize<EstoData>(infoData, options);
}
return default;
}
public override void Write(Utf8JsonWriter writer, EstoData value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
EstoJarelMaksTulemnus.cs
public class EstoJarelMaksTulemnus
{
public string[] Errors { get; set; }
[JsonConverter(typeof(StringToEstoDataConverter))]
public EstoData Data { get; set; }
public string Mac { get; set; }
}
Usage:
var tulemus = JsonSerializer.Deserialize<EstoJarelMaksTulemnus>(apiResponse, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Here's a working demo:
public class Program
{
public static void Main()
{
var data =
"{\"errors\":[],\"data\":\"{\\\"id\\\":\\\"iUW3YiDIz5Ahg5eO8hV7d3Cv7SVbZ913\\\",\\\"status\\\":\\\"CREATED\\\",\\\"purchase_url\\\":\\\"https:\\\\\\/\\\\\\/user.esto.ee\\\\\\/application\\\\\\/iUW3YiDIz5Ahg5eO8hV7d3Cv7SVbZ913\\\",\\\"merchant_reference\\\":\\\"158502\\\",\\\"amount\\\":93.95,\\\"currency\\\":\\\"EUR\\\",\\\"is_test\\\":true,\\\"return_url\\\":\\\"http:\\\\\\/\\\\\\/localhost:54274\\\\\\/CheckoutController\\\\\\/EstoJarelmaksOK?tellimus=104742\\\",\\\"notification_url\\\":\\\"http:\\\\\\/\\\\\\/localhost:54274\\\\\\/CheckoutController\\\\\\/EstoJarelmaksTeade?tellimus=104742\\\"}\",\"mac\":\"E9C3E61FC347D80200F542C43ABDCF464D537C37A609EC878F95B5F526271A2287F2D2E507B5A14FA3AF5F7A6D4CDECB6E8A1DBDF9A5633E0B3AD96DA35FA1C9\"}";
var tulemus = JsonSerializer.Deserialize<EstoJarelMaksTulemnus>(data, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Console.WriteLine(tulemus.Errors.Length);
Console.WriteLine(tulemus.Data.Id);
Console.WriteLine(tulemus.Data.Status);
Console.WriteLine(tulemus.Data.Purchase_url);
Console.WriteLine(tulemus.Data.Merchant_reference);
Console.WriteLine(tulemus.Data.Amount);
Console.WriteLine(tulemus.Data.Currency);
Console.WriteLine(tulemus.Data.Is_test);
Console.WriteLine(tulemus.Data.Return_url);
Console.WriteLine(tulemus.Data.Notification_url);
Console.WriteLine(tulemus.Mac);
}
}
public class StringToEstoDataConverter : JsonConverter<EstoData>
{
public override EstoData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
var infoData = jsonDoc.RootElement.GetString();
if (infoData != null)
return JsonSerializer.Deserialize<EstoData>(infoData, options);
}
return default;
}
public override void Write(Utf8JsonWriter writer, EstoData value, JsonSerializerOptions options)
{
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
public class EstoJarelMaksTulemnus
{
public string[] Errors { get; set; }
[JsonConverter(typeof(StringToEstoDataConverter))]
public EstoData Data { get; set; }
public string Mac { get; set; }
}
public class EstoData
{
public string Id { get; set; }
public string Status { get; set; }
public string Purchase_url { get; set; }
public string Merchant_reference { get; set; }
public decimal Amount { get; set; }
public string Currency { get; set; }
public bool Is_test { get; set; }
public string Return_url { get; set; }
public string Notification_url { get; set; }
}
Output:
0
iUW3YiDIz5Ahg5eO8hV7d3Cv7SVbZ913
CREATED
https://user.esto.ee/application/iUW3YiDIz5Ahg5eO8hV7d3Cv7SVbZ913
158502
93.95
EUR
True
http://localhost:54274/CheckoutController/EstoJarelmaksOK?tellimus=104742
http://localhost:54274/CheckoutController/EstoJarelmaksTeade?tellimus=104742
E9C3E61FC347D80200F542C43ABDCF464D537C37A609EC878F95B5F526271A2287F2D2E507B5A14FA3AF5F7A6D4CDECB6E8A1DBDF9A5633E0B3AD96DA35FA1C9
How to Deserialize complex JSON and create it as C# Object
You've got JSON containing JSON, basically - so you should expect to have to deserialize once. (If you can change the structure of the JSON to avoid this double-serialization, that would be better, admittedly, but I'll assume that's fixed.)
For example, you could have:
public class Root
{
public List<Value> Values { get; set; }
}
public class Value
{
// Add other properties if you need them
public string RawValue { get; set; }
}
Then:
string json = ...;
Root root = JsonConvert.DeserializeObject<Root>(json);
// This just takes the first value - we don't know whether you actually
// ever have more than one...
string rawValue = root.Values[0].RawValue;
JArray array = JArray.Parse(rawValue);
That assumes you're happy using JArray
/JObject
for the "embedded" objects. If you want to model those as well, you'd have:
public class Station
{
[JsonProperty("ID")]
public int Id { get; set; }
public int StationNo { get; set; }
// etc
}
... then for deserializing:
string json = ...;
Root root = JsonConvert.DeserializeObject<Root>(json);
// This just takes the first value - we don't know whether you actually
// ever have more than one...
string rawValue = root.Values[0].RawValue;
List<Station> stations = JsonConvert.DeserializeObject<List<Station>>(rawValue);
There shouldn't be any "extra" escaping by the time you've deserialized twice.
Deserializing nested JSON array inside nested JSON object in c#?
Install nuget Newtonsoft.Json
. Create next hierarchy:
using System;
using System.Collections.Generic;
using System.Globalization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
public class MyClass
{
[JsonProperty("container")]
public Container Container { get; set; }
}
public class Container
{
[JsonProperty("cans1")]
public Cans[] Cans1 { get; set; }
[JsonProperty("ids")]
[JsonConverter(typeof(DecodeArrayConverter))]
public long[] Ids { get; set; }
[JsonProperty("cans2")]
public Cans[] Cans2 { get; set; }
}
public class Cans
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("ids")]
public string[] Ids { get; set; }
}
And then
JsonConvert.DeserializeObject<MyClass>(yourJsonString);
UPD
Based on comment, try this:
var des = JsonConvert.DeserializeObject<MyClass>(t);
foreach(var arr in des.Container.Where(r => r.Key.StartsWith("cans")))
{
Console.WriteLine($"{arr.Key}");
foreach(var elem in arr.Value)
{
Console.WriteLine($" {elem.Value<string>("name")}");
}
}
public class MyClass
{
[JsonProperty("container")]
public Dictionary<string, JArray> Container { get; set; }
}
Related Topics
C# Adding Button with Value at Runtime
Wix - How to Run/Install Application Without Ui
Nunit VS. Visual Studio 2008's Test Projects for Unit Testing
How to Create a Product Key for My C# Application
How to Set Up HTML/Email Templates with ASP.NET
How to Wait for Async Method to Complete
Singleton by Jon Skeet Clarification
Passing Data to Master Page in ASP.NET MVC
Creating Composite Key Entity Framework
Lambda Expression Using Foreach Clause
Generic Base Class for Winform Usercontrol
Synchronized Scrolling of Two Scrollviewers Whenever Any One Is Scrolled in Wpf