Accessing deeply nested JSON objects in c# using NewtonSoft Deserialization - c#

I am having a very difficult time reaching some deeply nested objects in my JSON
I have a directory with roughly 500 JSON files that I need to read through, and output certain data from so I load the files like this:
public static void getJsonFiles()
{
int i = 0;
string directory = #"Z:\My_JSON_FILES\DataFilesForAnalysis\DataFilesAsJSON";
string[] jsonPath = Directory.GetFiles(directory, "*.json");
foreach(string item in jsonPath)
{
jsonReader(item, i);
i++;
}
}
Once I have the file loaded, I am reading it through File.ReadAllText so I am doing this:
public static void jsonReader(string item, int i)
{
string readJson = File.ReadAllText(item);
RootObject rootObj = JsonConvert.DeserializeObject<RootObject>(readJson);
var resReport = rootObj.ResultsReport;
...
I have created objects of all of the JSON using json2csharp, but when I try to access the deeply nested objects using dot notation (rootObj.ResultsReport.FinalReport.VariantProperties.VariantProperty.VariantName), I get an error 'Object does not contain a definition for FinalReport and no extension method FinalReport...'
My object definition looks like this:
public class VariantProperty
{
public string geneName { get; set; }
public string isVUS { get; set; }
public string variantName { get; set; }
}
public class VariantProperties
{
public string[] VariantProperty { get; set; }
}
public class FinalReport
{
public Object Application { get; set; }
public string ReportId { get; set; }
public string SampleName { get; set; }
public string Version { get; set; }
public Object Sample { get; set; }
public string PertinentNegatives { get; set; }
public Object Summaries { get; set; }
public Object VariantProperties { get; set; }
public Object Genes { get; set; }
public Object Trials { get; set; }
public Object References { get; set; }
public Object Signatures { get; set; }
public Object AAC { get; set; }
}
public class ResultsReport
{
public Object FinalReport { get; set; }
public Object VariantReport { get; set; }
}
public class RootObject
{
public Object ResultsReport { get; set; }
}
The JSON looks like this:
"ResultsReport": {
"CustomerInformation": null,
"FinalReport": {
"#xmlns:xsd": "http://www.w3.org/2001/XMLSchema",
"#StagingId": "XXXXXXXX",
"#clinicalId": "XXXXXXXX",
"Application": {
"ApplicationSettings": {
"ApplicationSetting": {
"Name": "Statement",
"Value": "XXXXXXXX"
}
}
},
"ReportId": "XXXXXXXX",
"SampleName": "XXXXXXXX",
"Version": "1",
"Sample": {
"FM_Id": "XXXXXXXX",
"SampleId": "XXXXXXXX",
"BlockId": "XXXXXXXX",
"TRFNumber": "XXXXXXXX",
"TestType": "XXXXXXXX",
"SpecFormat": "XXXXXXXX",
"ReceivedDate": "XXXXXXXX"
},
"PertinentNegatives": null,
"Summaries": {
"#alterationCount": "XXXXXXXX",
"#clinicalTrialCount": "XXXXXXXX",
"#resistiveCount": "XXXXXXXX",
"#sensitizingCount": "XXXXXXXX"
},
"VariantProperties": {
"VariantProperty": [
{
"#geneName": "BARD1",
"#isVUS": "true",
"#variantName": "P358_S364del"
},
{
"#geneName": "GATA2",
"#isVUS": "true",
"#variantName": "P161A"
},
{
"#geneName": "LRP1B",
"#isVUS": "true",
"#variantName": "V4109I"
},
{
"#geneName": "MLL2",
"#isVUS": "true",
"#variantName": "P1191L"
},
{
"#geneName": "NTRK1",
"#isVUS": "true",
"#variantName": "G18E"
},
{
"#geneName": "NUP98",
"#isVUS": "true",
"#variantName": "A447T"
},
{
"#geneName": "TET2",
"#isVUS": "true",
"#variantName": "D1121Y"
},
{
"#geneName": "WT1",
"#isVUS": "true",
"#variantName": "T377_G397>S"
}
]
}
What am I doing wrong? I've followed so many different examples but it just wont seem to work

Write properties like
public ResultsReport ResultsReport { get; set; }
public FinalReport FinalReport { get; set; }
You are using object as property type, thats wrong, it is not about JSON deserialization.

As Volkan said the issue isn't the JSON deserialization. I got your json working by structuring my classes like so:
public class VariantProperty
{
public string geneName { get; set; }
public string isVUS { get; set; }
public string variantName { get; set; }
}
public class VariantProperties
{
public List<VariantProperty> VariantProperty { get; set; }
}
public class FinalReport
{
public Object Application { get; set; }
public string ReportId { get; set; }
public string SampleName { get; set; }
public string Version { get; set; }
public Object Sample { get; set; }
public string PertinentNegatives { get; set; }
public Object Summaries { get; set; }
public VariantProperties VariantProperties { get; set; }
public Object Genes { get; set; }
public Object Trials { get; set; }
public Object References { get; set; }
public Object Signatures { get; set; }
public Object AAC { get; set; }
}
public class ResultsReport
{
public FinalReport FinalReport { get; set; }
}
public class RootObject
{
public ResultsReport ResultsReport { get; set; }
}

Related

Deserialize json on different classes

I have a json with different kind of blocks in it. There are simple block, like text, there's no problems in deserializing them, so I won't cover them up. The problems are with three kind of blocks: media, list and quiz:
{
"blocks": [
{
"type": "text",
"data": {
"text": "my awesome text",
"text_truncated": "<<<same>>>"
},
"cover": false,
"anchor": ""
},
{
"type": "media",
"data": {
"items": [
{
"title": "title1",
"author": "author1",
"image": {
"type": "image",
"data": {
"uuid": "eb19f678-3c9f-58f0-90c2-33bcb8237b17",
"width": 1024,
"height": 756,
"size": 448952,
"type": "jpg",
"color": "d3c58f",
"hash": "",
"external_service": []
}
}
},
{
"title": "title2",
"author": "author2",
"image": {
"type": "image",
"data": {
"uuid": "9274038e-1e9b-5cab-9db5-4936ce88a5c9",
"width": 750,
"height": 563,
"size": 164261,
"type": "jpg",
"color": "b7a58d",
"hash": "",
"external_service": []
}
}
}
],
"with_background": false,
"with_border": false
},
"cover": false,
"anchor": ""
},
{
"type": "list",
"data": {
"items": [
"foo",
"bar"
],
"type": "UL"
},
"cover": false,
"anchor": ""
},
{
"type": "quiz",
"data": {
"uid": "00bde249ff735f481620328765695",
"hash": "29d6bf8fec36eee3",
"tmp_hash": "",
"title": "When?",
"items": {
"a16203287650": "Ashita",
"a16203287651": "Kinou",
"a16203287742": "Ima"
},
"is_public": false,
"date_created": 1620328765
},
"cover": false,
"anchor": ""
}
]
}
These blocks's items property is different from one to another.
For serializing/deserializing I'm using System.Text.Json, built in net5.0. While I can deserialize this json's items into JsonElement and work with it further, I'd like to deserialize them to exact classes automatically, when I call JsonSerializer.Deserialize(...); e.g. IEnumerable<MediaBlockData>, IEnumerable<string> and so on, depending on what type (I mean json's property) it is.
While looking for answer I found out an article on mircosoft website, but I'm not wholly understand on how to implement it for my case:
https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to?pivots=dotnet-5-0
Update 1
My blocks implementation:
public class Block
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("data")]
public JsonElement Data { get; set; }
public IBlockData ParsedData { get; set; }
[JsonPropertyName("cover")]
public bool Cover { get; set; }
[JsonPropertyName("anchor")]
public string Anchor { get; set; }
private Type GetBlockDataType() => Type switch
{
"audio" => typeof(AudioBlockData),
"code" => typeof(CodeBlockData),
"delimiter" => typeof(DelimiterBlockData),
"header" => typeof(HeaderBlockData),
"image" => typeof(ImageBlockData),
"incut" => typeof(IncutBlockData),
"instagram" => typeof(InstagramBlockData),
"link" => typeof(LinkBlockData),
"list" => typeof(ListBlockData),
"media" => typeof(MediaBlockData),
"number" => typeof(NumberBlockData),
"person" => typeof(PersonBlockData),
"quiz" => typeof(QuizBlockData),
"quote" => typeof(QuoteBlockData),
"spotify" => typeof(SpotifyBlockData),
"telegram" => typeof(TelegramBlockData),
"text" => typeof(TextBlockData),
"tiktok" => typeof(TikTokBlockData),
"tweet" => typeof(TweetBlockData),
"universalbox" => typeof(UniversalBoxBlockData),
"video" => typeof(VideoBlockData),
"yamusic" => typeof(YaMusicBlockData),
_ => typeof(object)
};
public IBlockData GetBlockData()
{
var blockType = GetBlockDataType();
return (IBlockData)JsonSerializer.Deserialize(Data.ToString(), blockType);
}
}
public class ListBlockData : IBlockData
{
[JsonPropertyName("items")]
public IEnumerable<string> Items { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
}
public class QuizBlockData : IBlockData
{
[JsonPropertyName("uid")]
public string Uid { get; set; }
[JsonPropertyName("hash")]
public string Hash { get; set; }
[JsonPropertyName("tmp_hash")]
public string TempHash { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("items")]
public JsonElement Items { get; set; }
[JsonPropertyName("is_public")]
public bool IsPublic { get; set; }
[JsonPropertyName("date_created")]
public long DateCreated { get; set; }
}
public class MediaBlockData : IBlockData
{
[JsonPropertyName("items")]
public IEnumerable<MediaItem> Items { get; set; }
[JsonPropertyName("with_background")]
public bool WithBackground { get; set; }
[JsonPropertyName("with_border")]
public bool WithBorder { get; set; }
}
public class MediaItem : Block
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("author")]
public string Author { get; set; }
[JsonPropertyName("image")]
public Block Image { get; set; }
}
Update 2
Here's minimal reproducable code sample with json string in it:
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ConsoleApp1
{
public interface IBlockData
{
}
public class TextBlockData : IBlockData
{
[JsonPropertyName("text")]
public string Text { get; set; }
[JsonPropertyName("text_truncated")]
public string TextTruncated { get; set; }
}
public class MediaItem : Block
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("author")]
public string Author { get; set; }
[JsonPropertyName("image")]
public Block Image { get; set; }
}
public class QuizBlockData : IBlockData
{
[JsonPropertyName("uid")]
public string Uid { get; set; }
[JsonPropertyName("hash")]
public string Hash { get; set; }
[JsonPropertyName("tmp_hash")]
public string TempHash { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("items")]
public JsonElement Items { get; set; } // TODO: normal class instead of JsonElement
[JsonPropertyName("is_public")]
public bool IsPublic { get; set; }
[JsonPropertyName("date_created")]
public long DateCreated { get; set; }
}
public class MediaBlockData : IBlockData
{
[JsonPropertyName("items")]
public IEnumerable<MediaItem> Items { get; set; }
[JsonPropertyName("with_background")]
public bool WithBackground { get; set; }
[JsonPropertyName("with_border")]
public bool WithBorder { get; set; }
}
public class ListBlockData : IBlockData
{
[JsonPropertyName("items")]
public IEnumerable<string> Items { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
}
public class ImageBlockData : IBlockData
{
[JsonPropertyName("uuid")]
public Guid Uuid { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
[JsonPropertyName("size")]
public long Size { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("color")]
public string Color { get; set; }
[JsonPropertyName("hash")]
public string Hash { get; set; }
[JsonPropertyName("external_service")]
public IEnumerable<ExternalService> ExternalService { get; set; }
}
public class ExternalService
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
}
public class Block
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("data")]
public JsonElement Data { get; set; }
public IBlockData ParsedData { get; set; }
[JsonPropertyName("cover")]
public bool Cover { get; set; }
[JsonPropertyName("anchor")]
public string Anchor { get; set; }
private Type GetBlockDataType() => Type switch
{
"image" => typeof(ImageBlockData),
"list" => typeof(ListBlockData),
"media" => typeof(MediaBlockData),
"quiz" => typeof(QuizBlockData),
"text" => typeof(TextBlockData),
_ => typeof(object)
};
public IBlockData GetBlockData()
{
var blockType = GetBlockDataType();
return (IBlockData)JsonSerializer.Deserialize(Data.ToString(), blockType);
}
}
public class Root
{
[JsonPropertyName("blocks")]
public IEnumerable<Block> Blocks { get; set; }
}
internal static class Program
{
private static void Main()
{
var json = "{\"blocks\":[{\"type\":\"text\",\"data\":{\"text\":\"my awesome text\",\"text_truncated\":\"<<<same>>>\"},\"cover\":false,\"anchor\":\"\"},{\"type\":\"media\",\"data\":{\"items\":[{\"title\":\"title1\",\"author\":\"author1\",\"image\":{\"type\":\"image\",\"data\":{\"uuid\":\"eb19f678-3c9f-58f0-90c2-33bcb8237b17\",\"width\":1024,\"height\":756,\"size\":448952,\"type\":\"jpg\",\"color\":\"d3c58f\",\"hash\":\"\",\"external_service\":[]}}},{\"title\":\"title2\",\"author\":\"author2\",\"image\":{\"type\":\"image\",\"data\":{\"uuid\":\"9274038e-1e9b-5cab-9db5-4936ce88a5c9\",\"width\":750,\"height\":563,\"size\":164261,\"type\":\"jpg\",\"color\":\"b7a58d\",\"hash\":\"\",\"external_service\":[]}}}],\"with_background\":false,\"with_border\":false},\"cover\":false,\"anchor\":\"\"},{\"type\":\"list\",\"data\":{\"items\":[\"foo\",\"bar\"],\"type\":\"UL\"},\"cover\":false,\"anchor\":\"\"},{\"type\":\"quiz\",\"data\":{\"uid\":\"00bde249ff735f481620328765695\",\"hash\":\"29d6bf8fec36eee3\",\"tmp_hash\":\"\",\"title\":\"When?\",\"items\":{\"a16203287650\":\"Ashita\",\"a16203287651\":\"Kinou\",\"a16203287742\":\"Ima\"},\"is_public\":false,\"date_created\":1620328765},\"cover\":false,\"anchor\":\"\"}]}";
var root = JsonSerializer.Deserialize<Root>(json);
// Example on how it can be deserialized afterwards
foreach (Block block in root.Blocks)
{
block.ParsedData = block.GetBlockData();
}
}
}
}
Update 3
I've been able to deserialize blocks correctly (hope there are no major issues with this code), thanks to #dbc and this post:
Deserialize JSON array which has mixed values System.Text.JSON
Updated code:
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ConsoleApp1
{
public class BlockData
{
}
public class TextBlockData : BlockData
{
[JsonPropertyName("text")]
public string Text { get; set; }
[JsonPropertyName("text_truncated")]
public string TextTruncated { get; set; }
}
public class MediaItemBlock : Block
{
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("author")]
public string Author { get; set; }
[JsonPropertyName("image")]
public Block Image { get; set; }
}
public class QuizBlockData : BlockData
{
[JsonPropertyName("uid")]
public string Uid { get; set; }
[JsonPropertyName("hash")]
public string Hash { get; set; }
[JsonPropertyName("tmp_hash")]
public string TempHash { get; set; }
[JsonPropertyName("title")]
public string Title { get; set; }
[JsonPropertyName("items")]
public Dictionary<string, string> Items { get; set; }
[JsonPropertyName("is_public")]
public bool IsPublic { get; set; }
[JsonPropertyName("date_created")]
public long DateCreated { get; set; }
}
public class MediaBlockData : BlockData
{
[JsonPropertyName("items")]
public IEnumerable<MediaItemBlock> Items { get; set; }
[JsonPropertyName("with_background")]
public bool WithBackground { get; set; }
[JsonPropertyName("with_border")]
public bool WithBorder { get; set; }
}
public class ListBlockData : BlockData
{
[JsonPropertyName("items")]
public IEnumerable<string> Items { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
}
public class ImageBlockData : BlockData
{
[JsonPropertyName("uuid")]
public Guid Uuid { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
[JsonPropertyName("size")]
public long Size { get; set; }
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("color")]
public string Color { get; set; }
[JsonPropertyName("hash")]
public string Hash { get; set; }
[JsonPropertyName("external_service")]
public IEnumerable<ExternalService> ExternalService { get; set; }
}
public class ExternalService
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("id")]
public string Id { get; set; }
}
public class Block
{
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonPropertyName("data")]
public BlockData Data { get; set; }
[JsonPropertyName("cover")]
public bool Cover { get; set; }
[JsonPropertyName("anchor")]
public string Anchor { get; set; }
public static Type GetBlockDataType(string type) => type switch
{
"image" => typeof(ImageBlockData),
"list" => typeof(ListBlockData),
"media" => typeof(MediaBlockData),
"quiz" => typeof(QuizBlockData),
"text" => typeof(TextBlockData),
_ => typeof(object)
};
}
public class Root
{
[JsonPropertyName("blocks")]
public IEnumerable<Block> Blocks { get; set; }
}
internal static class Program
{
private static void Main()
{
var json = "{\"blocks\":[{\"type\":\"text\",\"data\":{\"text\":\"my awesome text\",\"text_truncated\":\"<<<same>>>\"},\"cover\":false,\"anchor\":\"\"},{\"type\":\"media\",\"data\":{\"items\":[{\"title\":\"title1\",\"author\":\"author1\",\"image\":{\"type\":\"image\",\"data\":{\"uuid\":\"eb19f678-3c9f-58f0-90c2-33bcb8237b17\",\"width\":1024,\"height\":756,\"size\":448952,\"type\":\"jpg\",\"color\":\"d3c58f\",\"hash\":\"\",\"external_service\":[]}}},{\"title\":\"title2\",\"author\":\"author2\",\"image\":{\"type\":\"image\",\"data\":{\"uuid\":\"9274038e-1e9b-5cab-9db5-4936ce88a5c9\",\"width\":750,\"height\":563,\"size\":164261,\"type\":\"jpg\",\"color\":\"b7a58d\",\"hash\":\"\",\"external_service\":[]}}}],\"with_background\":false,\"with_border\":false},\"cover\":false,\"anchor\":\"\"},{\"type\":\"list\",\"data\":{\"items\":[\"foo\",\"bar\"],\"type\":\"UL\"},\"cover\":false,\"anchor\":\"\"},{\"type\":\"quiz\",\"data\":{\"uid\":\"00bde249ff735f481620328765695\",\"hash\":\"29d6bf8fec36eee3\",\"tmp_hash\":\"\",\"title\":\"When?\",\"items\":{\"a16203287650\":\"Ashita\",\"a16203287651\":\"Kinou\",\"a16203287742\":\"Ima\"},\"is_public\":false,\"date_created\":1620328765},\"cover\":false,\"anchor\":\"\"}]}";
var options = new JsonSerializerOptions
{
Converters = { new BlockConverter() }
};
var root = JsonSerializer.Deserialize<Root>(json, options);
var ser = JsonSerializer.Serialize(root, options);
}
}
public class BlockConverter : JsonConverter<Block>
{
public override Block Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using JsonDocument doc = JsonDocument.ParseValue(ref reader);
// Get type for convert
string type = doc.RootElement.GetProperty("type").GetString();
// Create new block with default deserializer
Block block = JsonSerializer.Deserialize<Block>(doc.RootElement.GetRawText());
// Warning: recursive for types with blocks inside
block.Data = (BlockData)JsonSerializer.Deserialize(doc.RootElement.GetProperty("data").GetRawText(),
Block.GetBlockDataType(type), options);
return block;
}
public override void Write(Utf8JsonWriter writer, Block value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
Now I'm trying to serialize it back to string correctly, not yet happening.
Here's a version that desieralises this json without using a converter.
var media = new List<MediaBlock>();
var texts = new List<TextBlock>();
using var doc = JsonDocument.Parse(json);
foreach (var block in doc.RootElement.GetProperty("blocks").EnumerateArray())
{
switch (block.GetProperty("type").GetString())
{
case "text": texts.Add(Deserialise<TextBlock>(block.GetProperty("data"))); break;
case "media": media.Add(Deserialise<MediaBlock>(block.GetProperty("data"))); break;
// ...
}
}
var composite = new
{
Texts = texts,// compsite.Texts[0].Text is 'my awesome text'
Media = media // compsite.Media.Items[0].Author is 'author1'
};
// This is OK, but if you need speed, please have a look at
// https://stackoverflow.com/questions/58138793/system-text-json-jsonelement-toobject-workaround
static T Deserialise<T>(JsonElement e) => JsonSerializer.Deserialize<T>(e.GetRawText(), options: new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
The auxiliary classes I used are:
class MediaBlock
{
public List<MediaItem> Items { get; set; }
}
class MediaItem
{
public string Author { get; set; }
public string Title { get; set; }
// ...
}
class TextBlock
{
public string Text { get; set; }
}

Deserialize c# class structure containing RootObject

I have a JSON API result that I processed thru an online JSON-to-C# structure program to create the class structure. I've used this many times for other projects. The JSON returned everything along with a public class RootObject that references both the status and payload segments of the returned values.
I am using ASP.NET C# library to deserialize the result JSON using JavaScriptSerializer:
var vlist = new JavaScriptSerializer().Deserialize<TestStruct>(result);
My data structure looks like this (it's pretty standard):
public class TestStruct
{
public class Status
{
public int statusCode { get; set; }
public int errorType { get; set; }
public int errorCode { get; set; }
public string errorMessage { get; set; }
}
public class Payload
{
public VehicleStatusRpt vehicleStatusRpt { get; set; }
}
public class VehicleStatusRpt
{
public string statusType { get; set; }
//public ReportDate reportDate { get; set; }
//public VehicleStatus vehicleStatus { get; set; }
}
public class RootObject
{
public Status status { get; set; }
public Payload payload { get; set; }
}
}
The full JSON Result I'm trying to parse using the class structure is:
{
"status": {
"statusCode": 0,
"errorType": 0,
"errorCode": 0,
"errorMessage": "Success with response body"
},
"payload": {
"vehicleSummary": [
{
"vin": "KNDJX3AE8E7000080",
"vehicleIdentifier": "000080",
"modelName": "SOUL EV",
"modelYear": "2015",
"nickName": "My SOUL",
"generation": 1,
"extColorCode": "1D",
"trim": "EV",
"imagePath": {
"imageName": "2015-soul_ev-ev-1d.png",
"imagePath": "/content/dam/kia/us/owners/image/vehicle/2015/soul_ev/ev/",
"imageType": "1",
"imageSize": {
"length": "100",
"width": "100",
"uom": 0
}
},
"enrollmentStatus": 1,
"fatcAvailable": 1,
"telematicsUnit": 1,
"fuelType": 4,
"colorName": "CLEAR WHITE",
"activationType": 1,
"mileage": "24410",
"dealerCode": "MOBISDLR1",
"mobileStore": [
{
"osType": 0,
"downloadURL": "https://itunes.apple.com/us/app/kia-access-with-uvo-link/id1280548773?mt=8",
"image": {
"imageName": "iosImage.png",
"imagePath": "/content/dam/kia/us/owners/image/common/app/",
"imageType": "2",
"imageSize": {
"length": "100",
"width": "100",
"uom": 0
}
}
},
{
"osType": 1,
"downloadURL": "https://play.google.com/store/apps/details?id=com.myuvo.link",
"image": {
"imageName": "androidImage.png",
"imagePath": "/content/dam/kia/us/owners/image/common/app/",
"imageType": "2",
"imageSize": {
"length": "100",
"width": "100",
"uom": 0
}
}
}
],
"supportedApp": {
"appType": "5",
"appImage": {
"imageName": "app-access.png",
"imagePath": "/content/dam/kia/us/owners/image/common/app/access/",
"imageType": "2",
"imageSize": {
"length": "100",
"width": "100",
"uom": 0
}
}
},
"supportAdditionalDriver": 0,
"customerType": 0,
"vehicleKey": "937db044-8328-4188-a3d2-68ac3b183752"
}
]
}
}
I run this thru json2csharp.com to get the structure (the sample above is an abbreviated 'test' only
The deserializer returns an error: Invalid JSON Primitive (starting with Payload)
I see examples of using RootObject but with the Newtonsoft JSON libary. I would like to use the Microsoft library. Do I really need to switch to Newtonsoft JSON? If I can use JavaScriptSerializer library, how?
The classes that correspond to the JSON you posted are:
public class RootObject
{
public Status status { get; set; }
public Payload payload { get; set; }
}
public class Status
{
public int statusCode { get; set; }
public int errorType { get; set; }
public int errorCode { get; set; }
public string errorMessage { get; set; }
}
public class Payload
{
public List<VehicleSummary> vehicleSummary { get; set; }
}
public class VehicleSummary
{
public string vin { get; set; }
public string vehicleIdentifier { get; set; }
public string modelName { get; set; }
public string modelYear { get; set; }
public string nickName { get; set; }
public int generation { get; set; }
public string extColorCode { get; set; }
public string trim { get; set; }
public Image imagePath { get; set; }
public int enrollmentStatus { get; set; }
public int fatcAvailable { get; set; }
public int telematicsUnit { get; set; }
public int fuelType { get; set; }
public string colorName { get; set; }
public int activationType { get; set; }
public string mileage { get; set; }
public string dealerCode { get; set; }
public List<MobileStore> mobileStore { get; set; }
public SupportedApp supportedApp { get; set; }
public int supportAdditionalDriver { get; set; }
public int customerType { get; set; }
public string vehicleKey { get; set; }
}
public class Image
{
public string imageName { get; set; }
public string imagePath { get; set; }
public string imageType { get; set; }
public ImageSize imageSize { get; set; }
}
public class ImageSize
{
public string length { get; set; }
public string width { get; set; }
public int uom { get; set; }
}
public class MobileStore
{
public int osType { get; set; }
public string downloadURL { get; set; }
public Image image { get; set; }
}
public class SupportedApp
{
public string appType { get; set; }
public Image appImage { get; set; }
}
I was able to deserialize the JSON just fine using JavaScriptSerializer like this:
var root = new JavaScriptSerializer().Deserialize<RootObject>(result);
where result is the JSON string you posted in your question.
Note, however, that if you have placed your classes inside another class called TestStruct then you would need to take that into account and deserialize to TestStruct.RootObject instead, e.g.:
var root = new JavaScriptSerializer().Deserialize<TestStruct.RootObject>(result);
I was also able to deserialize the JSON using Json.Net in the same way with the JsonConvert class:
var root = JsonConvert.DeserializeObject<RootObject>(result);
Once you have the deserialized object, you can extract some interesting information from it like this:
foreach (var vs in root.payload.vehicleSummary)
{
Console.WriteLine(string.Format("{0} - {1} {2} {3}, {4} mi",
vs.vin, vs.colorName, vs.modelYear, vs.modelName, vs.mileage));
}
Here is a working demo using Json.Net: https://dotnetfiddle.net/Zh35be

Paste JSON as Classes Duplicates and Numbers Elements as Unique Classes

I have the following section of JSON coming from Shopify:
{
"orders": [
{
"total_line_items_price_set": {
"shop_money": {
"amount": "281.96",
"currency_code": "USD"
},
"presentment_money": {
"amount": "281.96",
"currency_code": "USD"
}
},
"total_discounts_set": {
"shop_money": {
"amount": "0.00",
"currency_code": "USD"
},
"presentment_money": {
"amount": "0.00",
"currency_code": "USD"
}
},
},
When I utilize the Paste JSON as Classes feature I am getting elements like "shop_money" and "presentment_money" repeated and numbered as individual classes.
public class Total_Line_Items_Price_Set
{
public Shop_Money shop_money { get; set; }
public Presentment_Money presentment_money { get; set; }
}
public class Shop_Money
{
public string amount { get; set; }
public string currency_code { get; set; }
}
public class Presentment_Money
{
public string amount { get; set; }
public string currency_code { get; set; }
}
public class Total_Discounts_Set
{
public Shop_Money1 shop_money { get; set; }
public Presentment_Money1 presentment_money { get; set; }
}
public class Shop_Money1
{
public string amount { get; set; }
public string currency_code { get; set; }
}
public class Presentment_Money1
{
public string amount { get; set; }
public string currency_code { get; set; }
}
I'm new to JSON and how it should be represented as classes in C# - this seems wrong. Is it possible to get a better result?
SOLUTION:
Based on the answer by Zakk Diaz I removed each class that was duplicated and numbered. Having done so I am successfully deserializing and making use of an array of order objects.
public class Orders
{
public Order[] orders { get; set; }
}
public class Order
{
// [...]
}
class Program
{
static void Main(string[] args)
{
// [...]
Orders testOrders = JsonConvert.DeserializeObject<Orders>(responseFromServer);
Console.WriteLine(testOrders.orders[0].id);
Console.WriteLine(testOrders.orders[0].total_line_items_price_set.shop_money.amount);
Console.WriteLine(testOrders.orders[0].line_items[1].price_set.shop_money.amount);
}
}
It looks fine for the most part, you can delete these classes and rename them in "Total_Discounts_Set"
public class Shop_Money1
{
public string amount { get; set; }
public string currency_code { get; set; }
}
public class Presentment_Money1
{
public string amount { get; set; }
public string currency_code { get; set; }
}

c# Serialize multiple nested objects to json

I have a need to serialize this from Objects, or possibly a object of objects in c#. I have tried multiple different ways to get the same output and have failed. Here is the JSON
{
"resourceType": "Observation",
"code": {
"coding": [
{
"system": "http://",
"code": "3637",
"display": "Gene"
}
],
"text": "Dip"
},
"subject": {
"reference": "Pat",
"display": ""
},
"valueString": "*1/*1",
"component": [
{
"code": {
"coding": [
{
"system": "http://",
"code": "",
"display": "Gene"
}
]
},
"valueCodeableConcept": {
"coding": [
{
"system": "http://",
"code": "",
"display": "CYP"
}
]
}
}
]
}
i created the following objects from this. I tried to make a object containing them and then use Newtonsoft to serialize it but I can not get it right
here are the objects
public class Rootobject
{
public string resourceType { get; set; }
public Code code { get; set; }
public Subject subject { get; set; }
public string valueString { get; set; }
public Component[] component { get; set; }
}
public class Code
{
public Coding[] coding { get; set; }
public string text { get; set; }
}
public class Coding
{
public string system { get; set; }
public string code { get; set; }
public string display { get; set; }
}
public class Subject
{
public string reference { get; set; }
public string display { get; set; }
}
public class Component
{
public Code1 code { get; set; }
public Valuecodeableconcept valueCodeableConcept { get; set; }
}
public class Code1
{
public Coding1[] coding { get; set; }
}
public class Coding1
{
public string system { get; set; }
public string code { get; set; }
public string display { get; set; }
}
public class Valuecodeableconcept
{
public Coding2[] coding { get; set; }
}
public class Coding2
{
public string system { get; set; }
public string code { get; set; }
public string display { get; set; }
}
As Sir Rufo pointed out(for completeness of answer)
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var obj = CreateRootObject();
var str = JsonConvert.SerializeObject( obj, Formatting.Indented );
Console.WriteLine(str);
}
private static Rootobject CreateRootObject()
{
var obj = new Rootobject() {
resourceType = "Observation",
code = new Code() {
coding = new Coding[] {
new Coding() {
system = "http://",
code = "3637",
display = "Gene",
},
},
text = "Dip",
},
subject = new Subject() {
reference = "Pat",
display = "",
},
valueString = "*1/*1",
component = new Component[] {
new Component() {
code = new Code2(){
coding = new Coding[] {
new Coding(){
system = "http://",
code = "3637",
display = "Gene",
},
},
},
valueCodeableConcept = new Valuecodeableconcept(){
coding = new Coding[] {
new Coding(){
system = "http://",
code = "",
display = "CYP",
},
},
},
},
},
};
return obj;
}
}
public class Rootobject
{
public string resourceType { get; set; }
public Code code { get; set; }
public Subject subject { get; set; }
public string valueString { get; set; }
public Component[] component { get; set; }
}
public class Code
{
public Coding[] coding { get; set; }
public string text { get; set; }
}
public class Coding
{
public string system { get; set; }
public string code { get; set; }
public string display { get; set; }
}
public class Subject
{
public string reference { get; set; }
public string display { get; set; }
}
public class Component
{
public Code2 code { get; set; }
public Valuecodeableconcept valueCodeableConcept { get; set; }
}
public class Code2
{
public Coding[] coding { get; set; }
}
public class Valuecodeableconcept
{
public Coding[] coding { get; set; }
}

Cannot deserialize the current JSON array (e.g. [1,2,3]) into type with complex and nested objects

I`m trying to build web api for complex object. For this aim I built the custom binder which deserialize this object from JSON.
My Customer Binder looks like:
var paramType = p_BindingContext.ModelType;
dynamic updatedParam = Activator.CreateInstance(paramType);
JsonReader reader = new JTokenReader(JObject.Parse
(p_ActionContext.Request.Content.ReadAsStringAsync().Result));
JObject jObject = JObject.Load(reader);
JsonSerializer serializer = new JsonSerializer();
serializer.Populate(jObject.CreateReader(), updatedParam);//Here the exception thorws
p_BindingContext.Model = updatedParam;
The object to serialize is very comlex:
public class ModelRegisterUserRequest{
public ModelUser User { get; set; }
public CampaignItem CampaignWithChosenProposal { get; set; }
public string ValidationToken { get; set; }
public string IVRToken { get; set; }
public string DealerID { get; set; }
public string SalePersonID { get; set; }
}
public class CampaignItem
{
public List<BannerItem> Banners { get; set; }
public string Code { get; set; }
public string CustomerInstruction { get; set; }
public string InfoLink { get; set; }
public string LobbySubTitle { get; set; }
public string LobbyTitle { get; set; }
public string MoreText { get; set; }
public uint NumOfColumns { get; set; }
public uint NumOfRows { get; set; }
public string OriginString { get; set; }
public int OriginInt { get; set; }
public List<ProposalItem> Proposals { get; set; }
public string RegulationsInfoLink { get; set; }
public string ServiceType { get; set; }
public string SubTitle { get; set; }
public string SWDefault { get; set; }
public string Title { get; set; }
}
public partial class ProposalItem
{
public List<string> EquipmentsCode { get; set; }
public string FeatureCode { get; set; }
public string InvalidReason { get; set; }
public bool IsExistsMoreInfo { get; set; }
public bool IsValid { get; set; }
public string LeadCode { get; set; }
public int ParamCombinationCode { get; set; }
public string ProductCode { get; set; }
public string ProductCombinationCode { get; set; }
public string ProposalCode { get; set; }
public List<ColumnItem> Columns { get; set; }
public List<MoreInfoItem> MoreInfoList { get; set; }
public List<string> PricePlans { get; set; }
public string ProductName { get; set; }
}
The Json is created with JSON.stringify command from Javascript code and look like :
{
"ValidationToken": "1cc6cca8-44d5-4042-af37-de6a0d198d17",
"AppID": "TST",
"campaignWithChosenProposal": {
"Banners": [
{
"LocationCodeString": "ManagerTab",
"LocationCodeInt": 256,
"MediaUrl": "BANNER 10"
}
],
"Code": "CAMP221",
"CustomerInstruction": "-1",
"InfoLink": "http://test.aspx",
"LobbySubTitle": "",
"LobbyTitle": "",
"MoreText": "",
"NumOfColumns": 0,
"NumOfRows": 0,
"OriginString": "INT",
"OriginInt": 4,
"Proposals": [
[
{
"EquipmentsCode": [
"5455"
],
"FeatureCode": "BE5455",
"InvalidReason": "",
"IsExistsMoreInfo": true,
"IsValid": true,
"LeadCode": "3792956510",
"ParamCombinationCode": 0,
"ProductCode": "OANTIVRP2",
"ProductCombinationCode": "0",
"ProposalCode": "291600010201C8F83661D5B82FD5F3603967588B7A72",
"Columns": [
{
"Content": ""
},
{
"Content": ""
},
{
"Content": ""
},
{
"Content": ""
},
{
"Content": ""
},
{
"Content": ""
}
],
"MoreInfoList": [
{
"Content": "3",
"MoreInfoTypesString": "LicenseFrom",
"MoreInfoTypesInt": 16
},
{
"Content": "3",
"MoreInfoTypesString": "LicenseTo",
"MoreInfoTypesInt": 32
},
{
"Content": "4.3",
"MoreInfoTypesString": "PricePeriod1",
"MoreInfoTypesInt": 64
}
],
"PricePlans": [
"O2"
],
"ProductName": ""
}
]
],
"RegulationsInfoLink": "http://www.test.aspx",
"ServiceType": "TST",
"SubTitle": "",
"SWDefault": "1",
"Title": ""
},
"User": {
"CurrentLicenseNumber": 0,
"CustomerID": "21670106",
"FirstName": "",
"LastName": "",
"RequestedLicenseNumber": "3",
"SubscriberPhoneNumber": "035448428",
"IdentityNumber": "058470",
"Email": "alexanrbe#gmail.com",
"RegistrationStatus": "NOTREGISTERED"
},
"SalePersonID": "3178364",
}
The Exception is thrown on serilization row and looks like:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type WebAPI.Models.Entities.Campaigns.CampaignObjects.ProposalItem' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
I spent nights for resolve this exception but did not find any solutions
Also the solutions on this site are excisted but not supports such complex problem.
https://stackoverflow.com/questions/11126242/using-jsonconvert-deserializeobject-to-deserialize-json-to-a-c-sharp-poco-class
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
Somebody met such JSON unexpected behaiviour and could help?
Thanks
According to your JSON data, the objects that you need to map to have to look like this (unless you have your own JsonDeserializer of course):
public class Banner
{
public string LocationCodeString { get; set; }
public int LocationCodeInt { get; set; }
public string MediaUrl { get; set; }
}
public class CampaignWithChosenProposal
{
public List<Banner> Banners { get; set; }
public string Code { get; set; }
public string CustomerInstruction { get; set; }
public string InfoLink { get; set; }
public string LobbySubTitle { get; set; }
public string LobbyTitle { get; set; }
public string MoreText { get; set; }
public int NumOfColumns { get; set; }
public int NumOfRows { get; set; }
public string OriginString { get; set; }
public int OriginInt { get; set; }
public List<List<>> Proposals { get; set; }
public string RegulationsInfoLink { get; set; }
public string ServiceType { get; set; }
public string SubTitle { get; set; }
public string SWDefault { get; set; }
public string Title { get; set; }
}
public class User
{
public int CurrentLicenseNumber { get; set; }
public string CustomerID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string RequestedLicenseNumber { get; set; }
public string SubscriberPhoneNumber { get; set; }
public string IdentityNumber { get; set; }
public string Email { get; set; }
public string RegistrationStatus { get; set; }
}
public class RootObject
{
public string ValidationToken { get; set; }
public string AppID { get; set; }
public CampaignWithChosenProposal campaignWithChosenProposal { get; set; }
public User User { get; set; }
public string SalePersonID { get; set; }
}
Here is a really cool tool (json2csharp) to help you out.

Categories