Deserialize Nested, Complex Json Object to Just a String C#

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:

  1. In your Body class, the TrackList property does not match the JSON. The corresponding property in the JSON is called track_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; }
    }
  2. You are attempting to deserialize into the Track class, but you should be deserializing to Root 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 :

Sample Image

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 :

Sample Image

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



Leave a reply



Submit