c# Serialize multiple nested objects to json - c#

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; }
}

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; }
}

C# Newton deserialize JSON with sub lists

Let's say that this is the API jsonresponse from Facebook (at the end).
Until now i am deserializing the newton jsongetting the id and created_time for each one, but the second one includes reactions which is a list and a comments element which is another list.
I am using the following to loop through posts:
var posts = JsonConvert.DeserializeObject<FacebookPostData>(fbData);
And the
for each post in posts....
id = post.id
How inside the loop that i am could loop to the post Reactions and post Comments.
The class that i have so far and working is:
public class FacebookPostData
{
public List<FacebookPost> Data { get; set; }
}
public class FacebookPost
{
public string id { get; set; }
public string created_time { get; set; }
}
The API response is:
{
"data": [{
"id": "",
"created_time": ""
},
{
"id": "",
"created_time": "",
"reactions": {
"data": [{
"id": "",
"name": "",
"type": ""
},
{
"id": "",
"name": "",
"type": ""
}
],
"paging": {
"cursors": {
"before": "",
"after": ""
}
}
},
"comments": {
"data": [{
"created_time": "",
"from": {
"name": "",
"id": ""
},
"message": "",
"id": ""
}],
"paging": {
"cursors": {
"before": "",
"after": ""
}
}
}
}
],
"paging": {
"previous": "",
"next": ""
}
}
Thank you!
Your classes could be structured in this way:
public class FacebookPostData
{
public List<FacebookPost> data { get; set; }
public Paging3 paging { get; set; }
public FacebookPostData()
{
this.data = new List<FacebookPost>();
this.paging = new Paging3();
}
}
public class FacebookPost
{
public string id { get; set; }
public string created_time { get; set; }
public Reactions reactions { get; set; }
public Comments comments { get; set; }
public FacebookPost()
{
this.reactions = new Reactions();
this.comments = new Comments();
}
}
public class Paging3
{
public string previous { get; set; }
public string next { get; set; }
}
public class Reactions
{
public List<Data2> data { get; set; }
public Paging paging { get; set; }
public Reactions()
{
this.data = new List<Data2>();
this.paging = new Paging();
}
}
public class Data2
{
public string id { get; set; }
public string name { get; set; }
public string type { get; set; }
}
public class Paging
{
public Cursors cursors { get; set; }
public Paging()
{
this.cursors = new Cursors();
}
}
public class Cursors
{
public string before { get; set; }
public string after { get; set; }
}
public class Comments
{
public List<Data3> data { get; set; }
public Paging2 paging { get; set; }
public Comments()
{
this.data = new List<Data3>();
this.paging = new Paging2();
}
}
public class Data3
{
public string created_time { get; set; }
public From from { get; set; }
public string message { get; set; }
public string id { get; set; }
public Data3()
{
this.from = new From();
}
}
public class Paging2
{
public Cursors2 cursors { get; set; }
public Paging2()
{
this.cursors = new Cursors2();
}
}
public class From
{
public string name { get; set; }
public string id { get; set; }
}
public class Cursors2
{
public string before { get; set; }
public string after { get; set; }
}
So, you can do something like this:
var posts = JsonConvert.DeserializeObject<FacebookPostData>(fbData);
foreach(var post in posts.data)
{
Console.WriteLine(post.id);
// Reactions...
foreach(var reaction in post.reactions.data)
{
Console.WriteLine(reaction.id);
}
// Comments...
foreach(var comment in post.comments.data)
{
Console.WriteLine(comment.id);
Console.WriteLine(comment.from.id);
Console.WriteLine(comment.from.name);
}
}
See this demo.
Hope this helps.

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; }
}

Convert Json String to C# Object List

I want to convert a json string to a Object list. Please help me. it would be more helpful if done by NewtonJson.
I tried, but its not working. I dont want all the values of that json. just which are mentioned in the MatrixModel
This is a Object
public class MatrixModel
{
public string S1 { get; set; }
public string S2 { get; set; }
public string S3 { get; set; }
public string S4 { get; set; }
public string S5 { get; set; }
public string S6 { get; set; }
public string S7 { get; set; }
public string S8 { get; set; }
public string S9 { get; set; }
public string S10 { get; set; }
public int ScoreIfNoMatch { get; set; }
}
This is the Json String
"[
{
"Question": {
"QuestionId": 49,
"QuestionText": "Whats your name?",
"TypeId": 1,
"TypeName": "MCQ",
"Model": {
"options": [
{
"text": "Rahul",
"selectedMarks": "0"
},
{
"text": "Pratik",
"selectedMarks": "9"
},
{
"text": "Rohit",
"selectedMarks": "0"
}
],
"maxOptions": 10,
"minOptions": 0,
"isAnswerRequired": true,
"selectedOption": "1",
"answerText": "",
"isRangeType": false,
"from": "",
"to": "",
"mins": "02",
"secs": "04"
}
},
"CheckType": "",
"S1": "",
"S2": "",
"S3": "",
"S4": "",
"S5": "",
"S6": "",
"S7": "",
"S8": "",
"S9": "Pratik",
"S10": "",
"ScoreIfNoMatch": "2"
},
{
"Question": {
"QuestionId": 51,
"QuestionText": "Are you smart?",
"TypeId": 3,
"TypeName": "True-False",
"Model": {
"options": [
{
"text": "True",
"selectedMarks": "7"
},
{
"text": "False",
"selectedMarks": "0"
}
],
"maxOptions": 10,
"minOptions": 0,
"isAnswerRequired": false,
"selectedOption": "3",
"answerText": "",
"isRangeType": false,
"from": "",
"to": "",
"mins": "01",
"secs": "04"
}
},
"CheckType": "",
"S1": "",
"S2": "",
"S3": "",
"S4": "",
"S5": "",
"S6": "",
"S7": "True",
"S8": "",
"S9": "",
"S10": "",
"ScoreIfNoMatch": "2"
}
]"
You can use json2csharp.com to Convert your json to object model
Go to json2csharp.com
Past your JSON in the Box.
Clik on Generate.
You will get C# Code for your object model
Deserialize by var model = JsonConvert.DeserializeObject<RootObject>(json); using NewtonJson
Here, It will generate something like this:
public class MatrixModel
{
public class Option
{
public string text { get; set; }
public string selectedMarks { get; set; }
}
public class Model
{
public List<Option> options { get; set; }
public int maxOptions { get; set; }
public int minOptions { get; set; }
public bool isAnswerRequired { get; set; }
public string selectedOption { get; set; }
public string answerText { get; set; }
public bool isRangeType { get; set; }
public string from { get; set; }
public string to { get; set; }
public string mins { get; set; }
public string secs { get; set; }
}
public class Question
{
public int QuestionId { get; set; }
public string QuestionText { get; set; }
public int TypeId { get; set; }
public string TypeName { get; set; }
public Model Model { get; set; }
}
public class RootObject
{
public Question Question { get; set; }
public string CheckType { get; set; }
public string S1 { get; set; }
public string S2 { get; set; }
public string S3 { get; set; }
public string S4 { get; set; }
public string S5 { get; set; }
public string S6 { get; set; }
public string S7 { get; set; }
public string S8 { get; set; }
public string S9 { get; set; }
public string S10 { get; set; }
public string ScoreIfNoMatch { get; set; }
}
}
Then you can deserialize as:
var model = JsonConvert.DeserializeObject<List<MatrixModel.RootObject>>(json);
public static class Helper
{
public static string AsJsonList<T>(List<T> tt)
{
return new JavaScriptSerializer().Serialize(tt);
}
public static string AsJson<T>(T t)
{
return new JavaScriptSerializer().Serialize(t);
}
public static List<T> AsObjectList<T>(string tt)
{
return new JavaScriptSerializer().Deserialize<List<T>>(tt);
}
public static T AsObject<T>(string t)
{
return new JavaScriptSerializer().Deserialize<T>(t);
}
}
using dynamic variable in C# is the simplest.
Newtonsoft.Json.Linq has class JValue that can be used. Below is a sample code which displays Question id and text from the JSON string you have.
string jsonString = "[{\"Question\":{\"QuestionId\":49,\"QuestionText\":\"Whats your name?\",\"TypeId\":1,\"TypeName\":\"MCQ\",\"Model\":{\"options\":[{\"text\":\"Rahul\",\"selectedMarks\":\"0\"},{\"text\":\"Pratik\",\"selectedMarks\":\"9\"},{\"text\":\"Rohit\",\"selectedMarks\":\"0\"}],\"maxOptions\":10,\"minOptions\":0,\"isAnswerRequired\":true,\"selectedOption\":\"1\",\"answerText\":\"\",\"isRangeType\":false,\"from\":\"\",\"to\":\"\",\"mins\":\"02\",\"secs\":\"04\"}},\"CheckType\":\"\",\"S1\":\"\",\"S2\":\"\",\"S3\":\"\",\"S4\":\"\",\"S5\":\"\",\"S6\":\"\",\"S7\":\"\",\"S8\":\"\",\"S9\":\"Pratik\",\"S10\":\"\",\"ScoreIfNoMatch\":\"2\"},{\"Question\":{\"QuestionId\":51,\"QuestionText\":\"Are you smart?\",\"TypeId\":3,\"TypeName\":\"True-False\",\"Model\":{\"options\":[{\"text\":\"True\",\"selectedMarks\":\"7\"},{\"text\":\"False\",\"selectedMarks\":\"0\"}],\"maxOptions\":10,\"minOptions\":0,\"isAnswerRequired\":false,\"selectedOption\":\"3\",\"answerText\":\"\",\"isRangeType\":false,\"from\":\"\",\"to\":\"\",\"mins\":\"01\",\"secs\":\"04\"}},\"CheckType\":\"\",\"S1\":\"\",\"S2\":\"\",\"S3\":\"\",\"S4\":\"\",\"S5\":\"\",\"S6\":\"\",\"S7\":\"True\",\"S8\":\"\",\"S9\":\"\",\"S10\":\"\",\"ScoreIfNoMatch\":\"2\"}]";
dynamic myObject = JValue.Parse(jsonString);
foreach (dynamic questions in myObject)
{
Console.WriteLine(questions.Question.QuestionId + "." + questions.Question.QuestionText.ToString());
}
Console.Read();
Output from the code =>
Please make sure that all properties are both the getter and setter. In case, any property is getter only, it will cause the reverting the List to original data as the JSON string is typed.
Please refer to the following code snippet for the same:
Model:
public class Person
{
public int ID { get; set; }
// following 2 lines are cause of error
//public string Name { get { return string.Format("{0} {1}", First, Last); } }
//public string Country { get { return Countries[CountryID]; } }
public int CountryID { get; set; }
public bool Active { get; set; }
public string First { get; set; }
public string Last { get; set; }
public DateTime Hired { get; set; }
}
public class ModelObj
{
public string Str { get; set; }
public List<Person> Persons { get; set; }
}
Controller:
[HttpPost]
public ActionResult Index(FormCollection collection)
{
var data = new ModelObj();
data.Str = (string)collection.GetValue("Str").ConvertTo(typeof(string));
var personsString = (string)collection.GetValue("Persons").ConvertTo(typeof(string));
using (var textReader = new StringReader(personsString))
{
using (var reader = new JsonTextReader(textReader))
{
data.Persons = new JsonSerializer().Deserialize(reader, typeof(List<Person>)) as List<Person>;
}
}
return View(data);
}
If there is no explicit need for a class (model), you can also use dynamic
List<dynamic> models = JsonConvert.DeserializeObject<List<dynamic>>(jsonString);
And then use dot to access whatever fields you need
models[0].MyField
Try to change type of ScoreIfNoMatch, like this:
public class MatrixModel
{
public string S1 { get; set; }
public string S2 { get; set; }
public string S3 { get; set; }
public string S4 { get; set; }
public string S5 { get; set; }
public string S6 { get; set; }
public string S7 { get; set; }
public string S8 { get; set; }
public string S9 { get; set; }
public string S10 { get; set; }
// the type should be string
public string ScoreIfNoMatch { get; set; }
}
The variables/parameters within the class definition requires { get; set; }
I was using like a variable declaration (stupid of me, because it was working for other scenarios) without
{ get; set; }
Because of which, whatever I send from the JavaScript, it was not being received in the Action method. It was always getting null or empty model.
Once the {get; set;} is added, it worked like charm.
I hope it helps someone who is coming from VB6 style of programming line.

Converting Json code to C# (numbers as keys)

I get some json code from web services in Windows Phone 8. I generate my entities class thanks to the site json2csharp (http://json2csharp.com/). But there is a web service that has strange json code, like this. There is numbering as keys (0,1,2):
{
"service": "MainMapService",
"func": "getPlacesByAxes",
"result": {
"0": {
"id": "13478",
"date": "0",
"id_cat": "1",
"id_cat_sub": "0",
"id_user": "0",
},
"2": {
"id": "23272",
"date": "0",
"id_cat": "1",
"id_cat_sub": "0",
"id_user": "667"
},
"1": {
"id": "21473",
"date": "0",
"id_cat": "1",
"id_cat_sub": "0",
"id_user": "0"
}
},
"args": [
"1",
"50.8",
"4.5",
"1"
]
}
And json2csharp generates classes like this... Each class for a number:
public class __invalid_type__0
{
public string id { get; set; }
public string date { get; set; }
public string id_cat { get; set; }
public string id_cat_sub { get; set; }
public string id_user { get; set; }
}
public class __invalid_type__2
{
public string id { get; set; }
public string date { get; set; }
public string id_cat { get; set; }
public string id_cat_sub { get; set; }
public string id_user { get; set; }
}
public class __invalid_type__1
{
public string id { get; set; }
public string date { get; set; }
public string id_cat { get; set; }
public string id_cat_sub { get; set; }
public string id_user { get; set; }
}
public class Result
{
public __invalid_type__0 __invalid_name__0 { get; set; }
public __invalid_type__2 __invalid_name__2 { get; set; }
public __invalid_type__1 __invalid_name__1 { get; set; }
}
public class RootObject
{
public string service { get; set; }
public string func { get; set; }
public Result result { get; set; }
public List<string> args { get; set; }
}
So, the problem comes from the numbering keys and there may be several numbers. Do you know how can I resolve this? I can't change the Json code...
Thank you in advance
This is far from elegant, but give it a try.
So, what is my idea:
I have created two classes
RootObject helper
public class YourJsonClass
{
public string service { get; set; }
public string func { get; set; }
public dynamic result { get; set; }
public string[] args { get; set; }
}
result helper
public class Item
{
public string id { get; set; }
public string date { get; set; }
public string id_cat { get; set; }
public string id_cat_sub { get; set; }
public string id_user { get; set; }
}
I'm using newtonsoft json
var m_res = JsonConvert.DeserializeObject<YourJsonClass>(YourJsonResponce);
foreach (dynamic numb in m_res.result)
{
string m_name = numb.Name; // it will be "1", "0" or whatever
string h = numb.Value.ToString();
var m_value = JsonConvert.DeserializeObject<Item>(h);
}
... indeed there are better ways, but i hope this will help (:

Categories