Deserialize nested, complex json object to just a string c#
You could use a JToken
to capture your unknown settings
during deserialization, then use a second property to allow you to access that JSON as a string if you need to.
Set up your class like this:
public class RootObject
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonIgnore]
public string Settings
{
get { return SettingsToken != null ? SettingsToken.ToString(Formatting.None) : null; }
set { SettingsToken = value != null ? JToken.Parse(value) : JValue.CreateNull(); }
}
[JsonProperty("settings")]
private JToken SettingsToken { get; set; }
}
Then deserialize as usual:
var root = JsonConvert.DeserializeObject<RootObject>(json);
The Settings
property will contain the settings
part of the JSON as a string. If you reserialize the object back to JSON then the settings
will retain whatever structure it had before.
You can also change the Settings
property to some other JSON string, as long as it is well-formed. (If it isn't, then an exception will be thrown immediately.)
Here is a round-trip demo: https://dotnetfiddle.net/thiaWk
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
How can I deserialise a complex and nested JSON?
Step 1:
Parse your JSON in a JSON parser website such as https://jsonparser.org
This will help you understand the content and how it will be translated as an object.
For example, your JSON string gives this result :
Step2:
Open the query tool of this website, this will help you find out the object path to the information you need.
For example, for your JSON string, to access the POI name :
Step 3:
In your Visual Studio project, install the NuGet package: Newtonsoft.Json and Microsoft.CSharp in your shared library.
If you are processing the JSON in a separate library, please also install the Newtonsoft.Json NuGet package in the main project.
Step 4:
If JSONstring is your JSON string :
using Newtonsoft.Json;
dynamic NewObject = JsonConvert.DeserializeObject<dynamic>(JSONstring);
string Name = NewObject.results[0].poi.name;
string Distance = NewObject.results[0].dist;
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
Using System.Text.Json to deserialize nested array of array json object
It will never work because the json string has no properties with the specified names.
Your json string must be deserialized into a dictionary.
Try this:
static void Main(string[] args)
{
string json = DownloadJsonData();
var provinces = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, Dictionary<string, Dictionary<string, string[]>>>>>(json);
foreach (var province in provinces)
{
Console.WriteLine("Province: {0}", province.Key);
var districts = province.Value;
foreach (var district in districts)
{
Console.WriteLine("\tDistrict: {0}", district.Key);
var sectors = district.Value;
foreach (var sector in sectors)
{
Console.WriteLine("\t\tSector: {0}", sector.Key);
var cells = sector.Value;
foreach (var cell in cells)
{
Console.WriteLine("\t\t\tCell: {0}", cell.Key);
var values = cell.Value;
foreach (var value in values)
{
Console.WriteLine("\t\t\t\t{0}", value);
}
}
}
}
}
Console.ReadKey();
}
private static string DownloadJsonData()
{
using var webClient = new System.Net.WebClient();
string result = webClient.DownloadString("https://raw.githubusercontent.com/ngabovictor/Rwanda/master/data.json");
return result;
}
System.Text.Json - Deserialize nested object as string
Found a right way how to correctly read the nested JSON object inside the JsonConverter
. The complete solution is the following:
public class SomeModel
{
public int Id { get; set; }
public string Name { get; set; }
[JsonConverter(typeof(InfoToStringConverter))]
public string Info { get; set; }
}
public class InfoToStringConverter : JsonConverter<string>
{
public override string Read(
ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
return jsonDoc.RootElement.GetRawText();
}
}
public override void Write(
Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
In the code itself there is no need even to create options:
var json = @"{
""Id"": 1,
""Name"": ""Some Name"",
""Info"": {
""Additional"": ""Fields"",
""Are"": ""Inside""
}
}";
var model = JsonSerializer.Deserialize<SomeModel>(json);
The raw JSON text in the Info
property contains even extra spaces introduced in the example for nice readability.
And there is no mixing of model representation and its serialization as remarked @PavelAnikhouski in his answer.
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.
Related Topics
Lifetime of ASP.NET Static Variable
How to Create a Dynamic Button Click Event on a Dynamic Button
Regular Expression for Finding 'Href' Value of a <A> Link
Start a .Net Process as a Different User
Copying from and to Clipboard Loses Image Transparency
Remove Weird Characters ( a with Hat) from SQL Server Varchar Column
Why File.Readalllinesasync() Blocks the UI Thread
Remove Items from One List in Another
Change a Web.Config Programmatically with C# (.Net)
Javascriptserializer.Deserialize - How to Change Field Names
Convert Integers to Written Numbers
How to Close a Login Form and Show the Main Form Without My Application Closing
Can You Develop Linux Applications with Xamarin
How to Load an Assembly to Appdomain with All References Recursively
How to Use Visual Studio Code to Develop Unity3D Projects in Ubuntu
Automatically Create an Enum Based on Values in a Database Lookup Table