parse Dynamic c# class from a json - c#

I want to build a dynamic class with a given JSON.
Atm i parse the json with
dynamic customConfig = JsonConvert.DeserializeObject(configJson);
and its working fine with other json then the given BUT my problem is that the names of the properties (here valueOne and valueTwo are "dynamic", i get always others)
i Know if i know the names i can get e.g. the description by customConfig.config.valueOne.description
But what can i do to get e.g. the description by dont have the name of valueOne?
configJson=
"config": {
"valueOne":{
"description": "My first example value.",
"defaultValue": "Example 1",
"isRequired":false
},
"valueTwo":{
"description": "My second example value.",
"defaultValue": "Example 2",
"isRequired":false
},
},
What i tried was to get it in a loop but i dont get it to another class.
foreach (var param in customConfig.config)
{
foreach (var item in param)
{
Config.config.description[i] = item.description;
}
i++;
}
item.description gets the right description but why i cant save it in the other class (which is also dynamic)?

You might have some other underlying logic issues with your loop and what you're trying to accomplish there, but to answer your specific question, you might need to initialize your "config" and "data" members of your CustomConfigModel class. For example...
public class CustomConfigModel
{
public CustomConfigModel()
{
this.data = new ExpandoObject();
this.config = new ExpandoObject();
}
public dynamic data { get; set; }
public dynamic config { get; set; }
}

I was able to access the description you want, I think but it is in this form (my output) :
Token key: 'config.valueOne' ->>>> 'description' : 'My first example value.'
Token key: 'config.valueTwo' ->>>> 'description' : 'My first example value.'
If you know main item name , "config", before hand , you can parse and get rid of it so that you'd have values : "valueOne" or "valueTwo". As you can see from my example code, you can get description values by iterating. You can develop further functionality from this example. Please let me know if this works for you.
Here is the example code:
class Program
{
static void Main(string[] args)
{
string configJson = #"{
'config': {
'valueOne':{
'description': 'My first example value.',
'defaultValue': 'Example 1',
'isRequired':false
},
'valueTwo':{
'description': 'My second example value.',
'defaultValue': 'Example 2',
'isRequired':false
},
}
}";
JObject customConfig = (JObject)JsonConvert.DeserializeObject(configJson);
var children = customConfig.Children().Children();
List<JToken> subList = new List<JToken>();
foreach (JToken token in children.Values())
{
string key = token.Path;
subList.AddRange(token.Values());
JToken subitem = subList.Find(q => q.Path.Contains("description"));
string desc = ((JProperty)subitem).Value.ToString();
Console.WriteLine("Token key: '" + key + "' ->>>> 'description' : '" + desc+"'");
}
}
}

At
Config.config.description[i] = item.description;
is description[i] null and i get an excception but why

Related

Given a JSON value, how do I get the parent's sibling value?

I have a .NET Core 3.1 C# application reading the following JSON doc:
{
"info": {
"_postman_id": "b"
},
"item": [
{
"name": "GetEntityById via APIM",
"item": [
{
"name": "Call 1",
"url": {
"raw": "urlforcall1"
}
},
{
"name": "Call 2",
"url": {
"raw": "urlforcall2"
}
}
]
}
]
}
I want to select the value for each item\item\name and each item\item\url\raw.
So, I'd like to end up with "Call 1":"urlforcall1" and "Call 2":"urlforcall2".
I've been playing around and can grab the value from the raw token with the following:
var jObject = JObject.Parse(jsonString);
var urls = jObject.SelectTokens("..raw");
How can I grab the value from its parent's sibling, name?
I hope this code will help you
using Newtonsoft.Json.Linq;
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
string json = #"
{
'info': {
'_postman_id': 'b'
},
'item': [
{
'name': 'GetEntityById via APIM',
'item': [
{
'name': 'Call 1',
'url': {
'raw': 'urlforcall1',
}
},
{
'name': 'Call 2',
'url': {
'raw': 'urlforcall2',
}
}
]
}
]
}";
dynamic d = JObject.Parse(json);
foreach(var item in d.item)
{
foreach(var innerItem in item.item)
{
Console.WriteLine($"'{innerItem.name}' : '{innerItem.url.raw}'");
}
}
}
}
}
Can be tested here https://dotnetfiddle.net/xDr90O
To answer your question directly, if you have a JToken you can navigate upward from there using the Parent property. In your case you would need to use it four times to get to the level you want:
The parent of the JValue representing the call URL string is a JProperty with the name raw
The parent of that JProperty is a JObject
The parent of that JObject is a JProperty with the name url
The parent of that JProperty is a JObject, which also contains the name property
From there you can navigate back down using indexer syntax to get the value of name.
So, you would end up with this:
var jObject = JObject.Parse(jsonString);
foreach (JToken raw in jObject.SelectTokens("..raw"))
{
string callName = (string)raw.Parent.Parent.Parent.Parent["name"];
string urlForCall = (string)raw;
}
You may flatten inner item array using SelectMany method into one sequence (since outer item is also an array), then get name and raw values directly by key
var jObject = JObject.Parse(jsonString);
var innerItems = jObject["item"]?.SelectMany(t => t["item"]);
foreach (var item in innerItems)
{
var name = item["name"];
var raw = item["url"]?["raw"];
}

checking if an item with a valid conditiona actually exist in an foreachloop

I have two Json files . One file (jOne) Specifies to check for the availability of something (some key and value) in the other JSON file (jTwo)
jOne :- Which specifies what are the required values that need to be looked up in the second JSON file
[
{
"IdInOne": "001",
"NameInOne": "Name_2"
},
{
"IdInOne": "002",
"NameInOne": "Name_3"
}
]
jTwo :- File Which is Supposed to have the values specifed in JOne
[
{
"IdInTwo": "001",
"NameInTwo": "Name_1"
},
{
"IdInTwo": "001",
"NameInTwo": "Name_2"
},
{
"IdInTwo": "001",
"NameInTwo": "Name_3"
},
{
"IdInTwo": "002",
"NameInTwo": "Name_4"
}
]
So what I am trying to do is check if a certain specified json key and value pair actually exist in a given separate JSON , so in the Specified example in my first JSON file the value IdInOne": "001",NameInOne": "Name_2" and I want to check if the 2nd JSON file actually has a key and value that matches EXACTLY . In the second JSON There are multiple matches where the IdInOne (001) is equal to the IdInTwo but only a single value has both the ID and Name which matches to a specified one.
I Simply want to validate this and print a message if the match is successful and print a separate value if the match is unsuccesful
Here is the Code that I have tried and I am finding it hard to check if a value actually exists
class Program
{
static void Main(string[] args)
{
string jOne = #"D:\DelTemp\test.json";
string jTwo = #"D:\DelTemp\test2.json";
string jOneContent = File.ReadAllText(jOne);
string jTwoContent = File.ReadAllText(jTwo);
var InfoInOne = JsonConvert.DeserializeObject<List<One>>(jOneContent);
var InfoInTwo = JsonConvert.DeserializeObject<List<Two>>(jTwoContent);
foreach (var itemInOne in InfoInOne)
{
foreach (var itemInTwo in InfoInTwo.Where(n => n.IdInTwo == itemInOne.IdInOne && n.NameInTwo==itemInOne.NameInOne))
{
if (itemInTwo.exists())
{
//sucess message must be printed
}
else
{
Console.WriteLine("Item not found" + itemInTwo.NameInTwo)
}
}
}
}
}
public class One
{
public string IdInOne { get; set; }
public string NameInOne { get; set; }
}
public class Two
{
public string IdInTwo { get; set; }
public string NameInTwo { get; set; }
}
Note :- A downside of my current implementation is bad performance I beileive so is there any better way to implement this . Also only want to print the Error message saying that required/specified object is not found after it has fully iterated and confirmed that it is not there in the second JSON file
Would Really appreciate any help on this
Edit :- The Interesct method does not work as I get the error Two' does not contain a definition for 'exists' and no accessible extension method 'exists' accepting a first argument of type 'Two'
You could use Enumerable.Except. For example,
var dataNotInInfoTwo = InfoInOne.Select(x=>new {ID=x.IdInOne,Name=x.NameInOne})
.Except(InfoInTwo.Select(x=>new {ID=x.IdInTwo,Name=x.NameInTwo}));
foreach(var item in dataNotInInfoTwo)
{
Console.WriteLine($"Data Not Found : ID : {item.ID}, Name:{item.Name}");
}
Output
Data Not Found : ID : 002, Name:Name_3
This is untested for your circumstance but I imagine will work...
Not sure if you want to compare all or any, so here is both:
// Will tell you if all the elements in InfoInOne are also found in InfoInTwo
if (InfoInOne.All(x => InfoInTwo.Contains(x)))
{
}
// Will give you a list of all the items found to be in both lists
var matches = InfoInOne.FindAll(x => InfoInTwo.Contains(x));
EDIT I missed the part where you want separate output for success and no success so for that you can use this:
foreach (var result in InfoInOne)
{
if(InfoInTwo.Contains(result)) //sucess message must be printed
else Console.WriteLine("Item not found" + result.NameInOne) // This in NameInOne, not NameInTwo
}
There should be no need to pick apart the fields here as the objects only contain primitive types, and will be considered equal, or to be contained, in the other list if they match exactly.

Serialize list of dictionaries into accepted DataTable Ajax object

I have a web application in which I'm retrieving some data into bootstrap table, what i want to do now is to use jQuery DataTable instead of the current as it has too much useful features.
Currently I'm retrieving the data from the server side using OOP approach, where a class object represents a data row in a particular table, and this object includes a dictionary which stores column names and values.
What I'm doing now is that I'm retrieving these class objects and append each dictionary of each object in a List<Item> and then serialize this list using JavaScriptSerializer object, and this object returns the following JSON format:
[
{
"slno":"2",
"status_message":"Lights still flashing",
"crm_services_id":"1", "subject_id":"Lights are flashing",
"severity_id":"5",
"user_id":"husain.alhamali",
"status_id":"1"
},
{
"slno":"3",
"status_message":"lights working fine",
"crm_services_id":"2",
"subject_id":"Lights are flashing",
"severity_id":"3",
"user_id":"husain.alhamali",
"status_id":"2"
}
]
When i tried to use this object to fill my DataTable AJAX I've got an error says:
Invalid JSON response
I saw some examples of a valid JSON response that is acceptable to a DataTable which is as follow:
{
"data": [
[
"Tiger Nixon",
"System Architect",
"Edinburgh",
"5421",
"2011/04/25",
"$320,800"
],
[
"Garrett Winters",
"Accountant",
"Tokyo",
"8422",
"2011/07/25",
"$170,750"
]
}
Now my question is is there any tool or plugin that could re-format my JSON string into an acceptable format like the one above?
With this HTML:
<table id="example"></table>
This JS will create a table:
var data = [{
"slno": "2",
"status_message": "Lights still flashing",
"crm_services_id": "1",
"subject_id": "Lights are flashing",
"severity_id": "5",
"user_id": "husain.alhamali",
"status_id": "1"
}, {
"slno": "3",
"status_message": "lights working fine",
"crm_services_id": "2",
"subject_id": "Lights are flashing",
"severity_id": "3",
"user_id": "husain.alhamali",
"status_id": "2"
}];
function getColumns(){
for(var i = 0; i < data.length; i++){
let columnsArray = [];
var keys = Object.keys(data[i]);
for(k in Object.keys(data[i])){
if(data[i].hasOwnProperty(keys[k])){
columnsArray.push({
"data":keys[k]
});
}
}
return columnsArray;
}
}
$(document).ready(function() {
var table = $('#example').DataTable({
"columns": getColumns(),
"data": data
});
});
Working example. Hope that helps.
dataTable require json data in return from ajax response having following keys
1. data
2. draw
3. recordsTotal
4. recordsFiltered
Use this:
var data = list.Select(u => u.GetType()
.GetProperties()
.Select(p => p.GetValue(u, null)));
example
public class User
{
public int userId { get; set; }
public string name { get; set; }
}
public class Programm
{
static void Main()
{
var list = new List<User>();
list.Add(new User
{
userId = 1,
name = "name 1",
});
list.Add(new User
{
userId = 2,
name = "name 2",
});
var data = list.Select(u => u.GetType()
.GetProperties()
.Select(p => p.GetValue(u, null)));
Console.WriteLine(new JavaScriptSerializer().Serialize(new
{
data = data
}));
}
}
result
{
"data" : [
["1", "name 1"],
["2", "name 2"]
]
}

How to get the name of a JSON object using? (C# Newtonsoft.JSON)

For those of you familiar with Minecraft, the 1.8 update stores the sounds as a file with an encrypted hash as the name (which you can really just change the extension to .ogg to play). There is an index stored as a JSON file in the assets folder which shows the proper sound name for each file with the encrypted hash name.
I'm trying to create a program that which the user types the name and it will find the sound(s) that contains that name. The index is stored in this fashion:
{ "objects":{"minecraft/sounds/mob/wither/idle2.ogg": {
"hash": "6b2f86a35a3cd88320b55c029d77659915f83239",
"size": 19332
},
"minecraft/lang/fil_PH.lang": {
"hash": "e2c8f26c91005a795c08344d601b10c84936e89d",
"size": 74035
},
"minecraft/sounds/note/snare.ogg": {
"hash": "6967f0af60f480e81d32f1f8e5f88ccafec3a40c",
"size": 3969
},
"minecraft/sounds/mob/villager/idle1.ogg": {
"hash": "a772db3c8ac37dfeb3a761854fb96297257930ab",
"size": 8605
},
"minecraft/sounds/mob/wither/hurt3.ogg": {
"hash": "a4cf4ebe4c475cd6a4852d6b4228a4b64cf5cb00",
"size": 16731
}
For example if the user types wither, it will grab the hashes for "minecraft/sounds/mob/wither/idle2.ogg"
and
"minecraft/sounds/mob/wither/hurt3.ogg"
My question is, how do I get the object names (the names, not the properties) to compare with the user's keyword string.
Sorry if I didn't use proper terminology for some words, I don't tinker with JSON files much. Correct my terminology as needed.
EDIT
This answer solves it a lot more nicely (without dynamic):
https://stackoverflow.com/a/32129497/563532
Original answer:
This works:
var obj = JsonConvert.DeserializeObject<dynamic>(#"{ ""objects"":{""minecraft/sounds/mob/wither/idle2.ogg"": {
""hash"": ""6b2f86a35a3cd88320b55c029d77659915f83239"",
""size"": 19332
},
""minecraft/lang/fil_PH.lang"": {
""hash"": ""e2c8f26c91005a795c08344d601b10c84936e89d"",
""size"": 74035
},
""minecraft/sounds/note/snare.ogg"": {
""hash"": ""6967f0af60f480e81d32f1f8e5f88ccafec3a40c"",
""size"": 3969
},
""minecraft/sounds/mob/villager/idle1.ogg"": {
""hash"": ""a772db3c8ac37dfeb3a761854fb96297257930ab"",
""size"": 8605
},
""minecraft/sounds/mob/wither/hurt3.ogg"": {
""hash"": ""a4cf4ebe4c475cd6a4852d6b4228a4b64cf5cb00"",
""size"": 16731
}
}
}");
var t = obj.objects;
var names = new HashSet<String>();
foreach(JProperty fileThing in t)
{
names.Add(fileThing.Name);
}
names.Dump();
Gives:
minecraft/sounds/mob/wither/idle2.ogg
minecraft/lang/fil_PH.lang
minecraft/sounds/note/snare.ogg
minecraft/sounds/mob/villager/idle1.ogg
minecraft/sounds/mob/wither/hurt3.ogg
You can also do this:
var t = obj.objects;
var names = new Dictionary<String, String>();
foreach(JProperty fileThing in t)
{
names.Add(fileThing.Name, (string)t[fileThing.Name].hash);
}
Which gives you a dictionary linking the original name to the hash:
minecraft/sounds/mob/wither/idle2.ogg -> 6b2f86a35a3cd88320b55c029d77659915f83239
minecraft/lang/fil_PH.lang -> e2c8f26c91005a795c08344d601b10c84936e89d
minecraft/sounds/note/snare.ogg -> 6967f0af60f480e81d32f1f8e5f88ccafec3a40c
minecraft/sounds/mob/villager/idle1.ogg -> a772db3c8ac37dfeb3a761854fb96297257930ab
minecraft/sounds/mob/wither/hurt3.ogg -> a4cf4ebe4c475cd6a4852d6b4228a4b64cf5cb00
Assuming you have a jsonString as a string variable.
jsonString = "";
JArray array = JArray.Parse(json);
foreach (JObject content in array.Children<JObject>())
{
foreach (JProperty prop in content.Properties())
{
Console.WriteLine(prop.Name);
}
}

Getting names of properties in JSON.NET with C#

I've been coding a Minecraft launcher for my personal use (source). I've gotten to the point where I need to parse a JSON file containing all available "profiles" already made by the official launcher. It looks like this:
{
"profiles": {
"1.6.2": {
"name": "1.6.2",
"gameDir": "C:\\Users\\Ilan\\AppData\\Roaming\\.ilan\\1.6.2mc",
"lastVersionId": "1.6.2",
"allowedReleaseTypes": [
"snapshot",
"release"
],
"playerUUID": "e2f423057b72487eb6f7f8ce877a8015"
},
"1.6.1": {
"name": "1.6.1",
"gameDir": "C:\\Users\\Ilan\\AppData\\Roaming\\.ilan\\1.6.1",
"lastVersionId": "1.6.1"
},
"13w38c": {
"name": "13w38c",
"lastVersionId": "13w38c",
"javaArgs": "-Xmx1G",
"allowedReleaseTypes": [
"snapshot",
"release"
],
"playerUUID": "e2f423057b72487eb6f7f8ce877a8015",
"useHopperCrashService": false
},
As you can see, there is an object called "profiles" and in it there are properties with variable names. I want to get the names of those properties, not their values. I don't know how to do so, I tried Value or just the profile .ToString() but both results give me the contents of the property itself, not the name of it. Is there a way to get the names?
Edit: the code that parses the profile JSON is:
string profileJSON = File.ReadAllText(Variables.profileJSONFile);
JObject profiles = JObject.Parse(profileJSON);
MessageBox.Show(profiles["profiles"].ToString());
foreach (JProperty profileAvail in profiles["profiles"])
{
MessageBox.Show(profileAvail.ToString());
}
Use Name property:
Gets the property name.
public string Name { get; }
MessageBox.Show(profileAvail.Name);
IDictionary< string, JToken > json = Jobject.Parse( strJson );
foreach (var kv in json)
{
Console.WriteLine( kv.Key );
}

Categories