Deserialize json on different classes - c#
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; }
}
Related
How do I compare two JSON Objects to get new JSON for changes like add,delete,change using c#
Can anyone help in getting the output Json by comparing two JSON which has same hierarchy, by showing JStatus as Change, Added, Delete. we have JStatus present in each Json, after comparison it will fill with status "change"/"add"/"delete", the values should be from new (2nd json) for changed objects, and value of old (in case of delete) json1. please help 1st Base JSON (output should treat this as base JSON) [{"Decision":{"id":"1","identifier":"Base1","dec_id":10,"JStatus":"","objects":[{"id":"1","identifier":"Base2","JStatus":""},{"id":"2","identifier":"Base3","JStatus":""}]}}] 2nd JSON [{"Decision":{"id":"2","identifier":"Base1","dec_id":12,"JStatus":"","objects":[{"id":"1","identifier":"Base2","JStatus":"","textitem":[{"id":"1","identifier":"Base3","JStatus":"","objNewActivity":[{"id":"1","identifier":"Base4","JStatus":""}],"objNewGebiedsaanwijzingen":[{"id":"1","identifier":"Base5","JStatus":""}],"objNewBegrippen":[{"id":"1","identifier":"Base6","JStatus":""}],"objNewLocation":null}]}]}}] OutPut required JSON [{"Decision":{"id":"2","identifier":"Base1","dec_id":12,"JStatus":"Change","objects":[{"id":"1","identifier":"Base2","JStatus":"","textitem":[{"id":"1","identifier":"Base3","JStatus":"Add","objNewActivity":[{"id":"1","identifier":"Base4","JStatus":"Add"}],"objNewGebiedsaanwijzingen":[{"id":"1","identifier":"Base5","JStatus":"Add"}],"objNewBegrippen":[{"id":"1","identifier":"Base6","JStatus":"Add"}],"objNewLocation":null}]},{"id":"2","identifier":"Base3","JStatus":"Delete"}]}}] I tried https://www.nuget.org/packages/JsonDiffer following but that only show me changes, var j1 = JToken.Parse(readJson("Json1.txt")); var j2 = JToken.Parse(readJson("Json2.txt")); var diff = JsonDifferentiator.Differentiate(j1, j2, OutputMode.Detailed, showOriginalValues: true);
This is PSEUDO CODE Because I do not know the specific logic you wish to employ to make your comparisons and/or overwrites. using Newtonsoft.Json; using System.Collections.Generic; namespace StackDemo5 { public class StackDemo5Main { string json1 = "{ \"LoginSettings\": { \"Type\": \"Test\", \"Login\": \"Bitcoin\", \"Password\": \"123456\", \"SHA1Login\": \"Some hash\", \"SHA1Password\": \"Some hash\" }, \"Info1\": {\"Is_Active\": false, \"Amount\": 12 }, \"Info2\": { \"Is_Active\": true, \"Amount\": 41 }}"; string json2 = "{ \"LoginSettings\": { \"Type\": \"\", \"Login\": \"\", \"Password\": \"\", \"SHA1Login\": \"\", \"SHA1Password\": \"\" }, \"Info1\": { \"Is_Active\": false, \"Amount\": 0 }, \"Info2\": { \"Is_Active\": false, \"Amount\": 0 }, \"Info3\": { \"Is_Active\": false, \"Amount\": 0 }, \"Info4\": { \"Is_Active\": false, \"Amount\": 0 }}"; public string CreateJsonAggregate() { Root first = JsonConvert.DeserializeObject<Root>(json1); Root second = JsonConvert.DeserializeObject<Root>(json2); Root third = new Root(); third.LoginSettings = first.LoginSettings; third.Info1 = first.Info1; third.Info2 = first.Info2; third.Info3 = second.Info3; third.Info4 = second.Info4; return JsonConvert.SerializeObject(third); } public class LoginSettings { public string Type { get; set; } public string Login { get; set; } public string Password { get; set; } public string SHA1Login { get; set; } public string SHA1Password { get; set; } } public class Info1 { public bool Is_Active { get; set; } public int Amount { get; set; } } public class Info2 { public bool Is_Active { get; set; } public int Amount { get; set; } } public class Info3 { public bool Is_Active { get; set; } public int Amount { get; set; } } public class Info4 { public bool Is_Active { get; set; } public int Amount { get; set; } } public class Root { public LoginSettings LoginSettings { get; set; } public Info1 Info1 { get; set; } public Info2 Info2 { get; set; } public Info3 Info3 { get; set; } public Info4 Info4 { get; set; } } } public class StackDemo6 { public string CreateJsonAggregate() { string input1 = "[{\"Decision\":{\"id\":\"1\",\"identifier\":\"Base1\",\"dec_id\":10,\"JStatus\":\"\",\"objects\":[{\"id\":\"1\",\"identifier\":\"Base2\",\"JStatus\":\"\"},{\"id\":\"2\",\"identifier\":\"Base3\",\"JStatus\":\"\"}]}}]"; string input2 = "[{\"Decision\":{\"id\":\"2\",\"identifier\":\"Base1\",\"dec_id\":12,\"JStatus\":\"\",\"objects\":[{\"id\":\"1\",\"identifier\":\"Base2\",\"JStatus\":\"\",\"textitem\":[{\"id\":\"1\",\"identifier\":\"Base3\",\"JStatus\":\"\",\"objNewActivity\":[{\"id\":\"1\",\"identifier\":\"Base4\",\"JStatus\":\"\"}],\"objNewGebiedsaanwijzingen\":[{\"id\":\"1\",\"identifier\":\"Base5\",\"JStatus\":\"\"}],\"objNewBegrippen\":[{\"id\":\"1\",\"identifier\":\"Base6\",\"JStatus\":\"\"}],\"objNewLocation\":null}]}]}}]"; Root input1Deserialized = JsonConvert.DeserializeObject<Root>(input1); Root input2Deserialized = JsonConvert.DeserializeObject<Root>(input2); Root resultObject = new Root(); // Build you comparison logic: int dec_id; if (input1Deserialized.Decision.dec_id > input2Deserialized.Decision.dec_id) { dec_id = input1Deserialized.Decision.dec_id; } else { dec_id = input2Deserialized.Decision.dec_id; } resultObject.Decision.dec_id = dec_id; //etc. return JsonConvert.SerializeObject(result); } } // Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse); public class ObjNewActivity { public string id { get; set; } public string identifier { get; set; } public string JStatus { get; set; } } public class ObjNewGebiedsaanwijzingen { public string id { get; set; } public string identifier { get; set; } public string JStatus { get; set; } } public class ObjNewBegrippen { public string id { get; set; } public string identifier { get; set; } public string JStatus { get; set; } } public class Textitem { public string id { get; set; } public string identifier { get; set; } public string JStatus { get; set; } public List<ObjNewActivity> objNewActivity { get; set; } public List<ObjNewGebiedsaanwijzingen> objNewGebiedsaanwijzingen { get; set; } public List<ObjNewBegrippen> objNewBegrippen { get; set; } public object objNewLocation { get; set; } } public class Object { public string id { get; set; } public string identifier { get; set; } public string JStatus { get; set; } public List<Textitem> textitem { get; set; } } public class Decision { public string id { get; set; } public string identifier { get; set; } public int dec_id { get; set; } public string JStatus { get; set; } public List<Object> objects { get; set; } } public class Root { public Decision Decision { get; set; } } } The trick is to create a generic model that can hold the most possible data, then serialize an object set from all your input strings, then do some sort of logic comparison, here I just did a comparison on dec_id, because I have no idea what your model does, and I don't speak dutch. Also do write unit tests to validate your logic, it helps. If you need to generate a new model object in C#, simply use this website from your template, to get a new class structure: https://json2csharp.com/
How to bind this json and read specific key value
I have below json which I would like to read it in a list. below are the classes and model defined and the code by which I am trying to read. I am getting null value on binding. I am not sure how should i achieve this. So for example if I have multiple rules, I would like to read each one based on the condition passed. Please see my last sample code for better understanding. Sample Json: {"TableStorageRule": { "Rules": [ { "Name": "filterRule1", "DataFilter": { "DataSetType": "Settings1" }, "TableSettings": { "AzureTable": { "Account": "account1", "Table": "table1", "Key": "key1" }, "SchemaBaseUri": "https://test.web.core.windows.net/" } }, { "Name": "filterRule2", "DataFilter": { "DataSetType": "Settings2" }, "TableSettings": { "AzureTable": { "Account": "account2", "Table": "table2", "Key": "key2" }, "SchemaBaseUri": "https://test2.web.core.windows.net/" } } ] }} Model and Code: public class TableStoreSettings { public class AzureTableSettings { public string Account { get; set; } public string Key { get; set; } public string Table { get; set; } } public AzureTableSettings AzureTable { get; set; } public Uri SchemaBaseUri { get; set; } } public class TableStorageRule { public string Name { get; set; } public TwisterDataFilter DataFilter { get; set; } public TableStoreSettings TableSettings { get; set; } } public class TableStorageConfiguration { public IEnumerable<TableStorageRule> Rules { get; set; } = new List<TableStorageRule>(); } code by which I am trying to read: var builder = new ConfigurationBuilder() .SetBasePath(Path.Combine(Root)) .AddJsonFile("appsettings.json", optional: false); var config = builder.Build(); var tableStorageOutput = new TableStorageRule(); config.GetSection("TableStorageRule").Bind(tableStorageOutput); var nameOfFilter = tableStorageOutput.Name; if (tableStorageOutput.Name == "filterRule1") { var accountname = tableStorageOutput.TableSettings.AzureTable.Account; } on above I only get first filtername1 , i dont get other filternames and so on...though on GetSection() i see all the values in quick watch.
this is correct models from your JSON file : public class DataFilter { public string DataSetType { get; set; } } public class AzureTable { public string Account { get; set; } public string Table { get; set; } public string Key { get; set; } } public class TableSettings { public AzureTable AzureTable { get; set; } public string SchemaBaseUri { get; set; } } public class Rule { public string Name { get; set; } public DataFilter DataFilter { get; set; } public TableSettings TableSettings { get; set; } } public class TableStorageRule { public List<Rule> Rules { get; set; } } public class Root { public TableStorageRule TableStorageRule { get; set; } } for test you can read your JSON file and get values (maybe change models solve your problem in your code): string json = File.ReadAllText(jsonFilePath); Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(json);
How to read the json string through C# code in runtime?
{ "StudentInformation": { "rollNumber": null, "isClassLeader": false, "result": "Pass" }, "CollegeInformation": { "allClass": ["A", "B"], "currencyAccepted": "INR", "calendarDates": [], "currencyCode": "INR", "collegeCode": null, "hasBulidingFundPrices": false, "hasHostel": false, "hasSecurityFares": false }, "Collegetrips": [{ "tripsdate": [{ "departureTripDate": "2017-08-15 00:00:00", "Places": [{ "destination": "Bombay", "price": [{ "priceAmount": 1726 }] }] }] }] } In the above json file i need to retrieve only "priceAmount": 1726. Please anyone suggest how can able to achieve?
You can use System.Web.Script.Serialization (you need to add a reference to System.Web.Extensions): dynamic json = new JavaScriptSerializer() .DeserializeObject(jsonString); decimal price = json["Collegetrips"][0] ["tripsdate"][0] ["Places"][0] ["price"][0] ["priceAmount"]; // 1726 Note that you can pretty much traverse the json in this manner using indexes and key names.
Hi try this, public void Main() { string sJSON = "{\"StudentInformation\": {\"rollNumber\": null,\"isClassLeader\": false,\"result\": \"Pass\"},\"CollegeInformation\": {\"allClass\": [\"A\", \"B\"],\"currencyAccepted\": \"INR\",\"calendarDates\": [],\"currencyCode\": \"INR\",\"collegeCode\": null,\"hasBulidingFundPrices\": false,\"hasHostel\": false,\"hasSecurityFares\": false},\"Collegetrips\": [{\"tripsdate\": [{\"departureTripDate\": \"2017-08-15 00:00:00\",\"Places\": [{\"destination\": \"Bombay\",\"price\": [{\"priceAmount\": 1726}]}]}]}]}"; Rootobject obj = Newtonsoft.Json.JsonConvert.DeserializeObject<Rootobject>(sJSON); Price price = obj.Collegetrips.Select(ct => { var r = ct.tripsdate.Select(td => { var r1 = td.Places.Select(p => { Price itemPrice = p.price.FirstOrDefault(); return itemPrice; }).FirstOrDefault(); return r1; }).FirstOrDefault(); return r; }).FirstOrDefault(); if (price != null) Console.Write(price.priceAmount); else Console.Write("Not Found!"); } public class Rootobject { public Studentinformation StudentInformation { get; set; } public Collegeinformation CollegeInformation { get; set; } public Collegetrip[] Collegetrips { get; set; } } public class Studentinformation { public object rollNumber { get; set; } public bool isClassLeader { get; set; } public string result { get; set; } } public class Collegeinformation { public string[] allClass { get; set; } public string currencyAccepted { get; set; } public object[] calendarDates { get; set; } public string currencyCode { get; set; } public object collegeCode { get; set; } public bool hasBulidingFundPrices { get; set; } public bool hasHostel { get; set; } public bool hasSecurityFares { get; set; } } public class Collegetrip { public Tripsdate[] tripsdate { get; set; } } public class Tripsdate { public string departureTripDate { get; set; } public Place[] Places { get; set; } } public class Place { public string destination { get; set; } public Price[] price { get; set; } } public class Price { public int priceAmount { get; set; } }
I use: http://json2csharp.com/ to get a class representing the Json Object. public class StudentInformation { public object rollNumber { get; set; } public bool isClassLeader { get; set; } public string result { get; set; } } public class CollegeInformation { public List<string> allClass { get; set; } public string currencyAccepted { get; set; } public List<object> calendarDates { get; set; } public string currencyCode { get; set; } public object collegeCode { get; set; } public bool hasBulidingFundPrices { get; set; } public bool hasHostel { get; set; } public bool hasSecurityFares { get; set; } } public class Price { public int priceAmount { get; set; } } public class Place { public string destination { get; set; } public List<Price> price { get; set; } } public class Tripsdate { public string departureTripDate { get; set; } public List<Place> Places { get; set; } } public class Collegetrip { public List<Tripsdate> tripsdate { get; set; } } public class JsonResponse { public StudentInformation StudentInformation { get; set; } public CollegeInformation CollegeInformation { get; set; } public List<Collegetrip> Collegetrips { get; set; } } After that I use Newtonsoft.Json to fill the Class: using Newtonsoft.Json; namespace GitRepositoryCreator.Common { class JObjects { public static string Get(object p_object) { return JsonConvert.SerializeObject(p_object); } internal static T Get<T>(string p_object) { return JsonConvert.DeserializeObject<T>(p_object); } } } You can call it like that: JsonResponse jsonClass = JObjects.Get<JsonResponse>(stringJson); string stringJson = JObjects.Get(jsonClass); PS: If your json variable name is no valid C# name you can fix that like this: public class Exception { [JsonProperty(PropertyName = "$id")] public string id { get; set; } public object innerException { get; set; } public string message { get; set; } public string typeName { get; set; } public string typeKey { get; set; } public int errorCode { get; set; } public int eventId { 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; } }
Accessing deeply nested JSON objects in c# using NewtonSoft Deserialization
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; } }