Dynamically Select Required JSON information - c#

I need to deserialize some JSON but the problem is that all of my JSON objects don't have the exact same format.
Here is an example of the JSON that I have to deserialize :
[
{
"Player_Name": "Zlatan Ibrahimovic",
"Country": "Sweeden",
"Other_Informations": {
"Information1": [
]
},
},
{
"Player_Name": "Pavel Nedved",
"Country": "Czech Republic",
"Personal_Honours":
{
"Ballon_DOr": "One",
},
"Other_Informations": {
"Information1": [
]
},
},
{
"Player_Name": "Zinedine Zidane",
"Country": "Sweeden",
"Other_Informations": {
"Information1": [
{
"name": "example",
}
]
},
}
]
As you can see, some fields appear only for some objects for example "Personal_Honours".
I need to deserialize the JSON into this class :
public class PlayerData
{
public string Name { get; set; }
public string BallonDor {get; set; }
public string Information1{ get; set; }
public string Country{ get; set; }
}
I use this method which is really long and blocks my app :
(In this exmple I use Json that comes frome a textfile but usually I have to make a REST request..)
StreamReader reader = File.OpenText("TextFile1.txt");
List<PlayerData> DataList;
dynamic value= JsonConvert
.DeserializeObject<dynamic>(reader.ReadToEnd());
DataList = new List<PlayerData>();
foreach (dynamic data in value)
{
if (data.Personal_Honours == null)
{
if (data.Other_Informations.Information1 == null)
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
});
}
else
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
Information1 = data.Informations.Information1
});
}
}
else
{
if (data.Other_Informations.Information1 == null)
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
BallonDor = data.Personal_Honours.Ballon_DOr
});
}
else
{
DataList.Add(new PlayerData
{
Name = data.Player_Name,
Country = data.Country,
BallonDor = data.Personal_Honours.Ballon_DOr,
Information1 = data.Informations.Information1
});
}
}
}
This method is working but it is not efficient and blocks my UI.
How can I do to create a new "PlayerData" object without having all of those 'else if' statements ?
Thank you !
P.S : The question is different from this one Filter JSon Information
EDIT :
Here is how I got the RunTimeBinderExcepetion :
List<PlayerData> datalist = new List<PlayerData>();
foreach (dynamic pl in timeline)
{
datalist.Add(new PlayerData
{
Name = pl.Player_Name ,
Country = pl.Country ,
BallonDor = pl.Personal_Honours.Ballon_Dor,
Information1 = pl.Other_Informations.Information1.name
});
}

You got exception because some data doesn't have Personal_Honours property for example. Then you tried to access Ballon_Dor property from a null reference which trigger the exception. This way will work for sample JSON you posted :
List<PlayerData> datalist = new List<PlayerData>();
foreach (dynamic pl in timeline)
{
//object initialization is done later just for the sake of easier debugging
//...so we can spot unexpected data which cause exception easily
var Name = pl.Player_Name;
var Country = pl.Country;
var BallonDor = pl.Personal_Honours != null ? pl.Personal_Honours.Ballon_Dor : null;
var Information1 = pl.Other_Informations.Information1.Count > 0 ?
pl.Other_Informations.Information1[0].name :
null;
datalist.Add(new PlayerData
{
Name = Name ,
Country = Country ,
BallonDor = BallonDor,
Information1 = Information1
});
}
...but above approach is still error prone depending on how consistent is the JSON string we have. More robust approach is maybe to have model classes to map JSON string as suggested by #L.B in comment.

Related

Add anonymous or an object properties to JObject in C#

I have following class
public class Customer{
public string name {get;set;}
public JObject properties {get;set;} = new JObject();
}
Now I am adding properties to customer properties
var customer = new Customer();
customer.properties["wow-123:test"] = new {
name = "Mark,
company = new {
name = "LLC",
address = new {
city= "London" } } }
In the end I want this to look like:
"properties": {
"wow-123:test": [
{
"name": "Mark",
"company": {
"name": "LLC",
"address ": {
"city": "London"
}
}
}
]
}
I keep getting error that it cannot convert it to Jtoken. If I change it to ToString then it is not in JSON format. How can I achieve the above?
First, you need to explicitly convert your anonymously typed object to a JToken:
customer.properties["wow-123:test"] = JToken.FromObject(new { ... });
However, since your example output shows that the contents of wow-123:test are an array (..."wow-123:test": [ { "name":...) , what you actually need might be
customer.properties["wow-123:test"] = new JArray(JToken.FromObject(new { ... } ));
which will create a single-element array containing your anonymously typed object.
fiddle

Compare JSON array and JSON object: Cannot convert Array to String error

I am trying to compare json value and based on that i want to update the existing value,for example, currently we have "value" : [r0] in json, i want to compare and if value : [r0] ,then update it to [r0,r1] but iam hiting error that it cannot compare and there is a cast issue, could someone suggest what could be done
public void updateJsonParameter(string file)
{
try
{
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
var jobject = JObject.Parse(file);
var ringvalue = (string)jobject["properties"]["parameters"]["ringValue"]["value"]; // unable to case here and compare
jobject["properties"]["parameters"]["ringValue"]["value"] = array; // able to update value but i want to update after comparing the existing values
var result = JsonConvert.SerializeObject(jobject);
}
following is the json format
{
"properties": {
"displayName": "jayatestdefid",
"description": "test assignment through API",
"metadata": {
"assignedBy": "xyz#gmail.com"
},
"policyDefinitionId": "/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters": {
"ringValue": {
"value": ["r0"]
}
},
"enforcementMode": "DoNotEnforce",
}
}
jobject.properties.parameters.ringValue.value is an array ["r0"] with one element "r0". If you want to check if it's an array with one element and that element is "r0", do exactly that:
var ringvalue = jobject["properties"]["parameters"]["ringValue"]["value"];
if(ringvalue.length == 1 && ringvalue[0] == "r0")
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
You could compare the ringvalue (which is an JArray) using JArray.DeepEquals and then replace if the comparison returns true. For example,
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
JArray valueToCompare = new JArray(new[]{"r0"});
var ringvalue = (JArray)jobject["properties"]["parameters"]["ringValue"]["value"];
if(JArray.DeepEquals(ringvalue,valueToCompare))
{
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
}
First, as Klaycon said in his answer, it's worth noting that your "value" is not a single string. In json, whenever you see [ and ] then you have a collection, or an array, or a list.
When I work with json strings, I always like to be able to convert them into a strongly typed object. There is a very handy online tool I use all the time: http://json2csharp.com/
I took your json string that you provided and pasted it into that website. Here is that your object(s) look like when converted into c# classes:
public class RootObject // You can name this whatever you want
{
public Properties properties { get; set; }
}
public class Metadata
{
public string assignedBy { get; set; }
}
public class RingValue
{
public List<string> value { get; set; }
}
public class Parameters
{
public RingValue ringValue { get; set; }
}
public class Properties
{
public string displayName { get; set; }
public string description { get; set; }
public Metadata metadata { get; set; }
public string policyDefinitionId { get; set; }
public Parameters parameters { get; set; }
public string enforcementMode { get; set; }
}
Now, we can easily do the logic you need as follows:
// This is your json string, escaped and turned into a single string:
string file = "{ \"properties\": { \"displayName\": \"jayatestdefid\", \"description\": \"test assignment through API\", \"metadata\": { \"assignedBy\": \"xyz#gmail.com\" }, \"policyDefinitionId\": \"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test\", \"parameters\": { \"ringValue\": { \"value\": [\"r0\"] } }, \"enforcementMode\": \"DoNotEnforce\", }}";
// Convert your json string into an instance of the RootObject class
RootObject jobject = JsonConvert.DeserializeObject<RootObject>(file);
// Get a list of all the "values"
List<string> values = jobject.properties.parameters.ringValue.value;
// Loop over your colleciton of "value" and do your logic
for (int i = 0; i < values.Count; ++i)
{
if (values[i] == "r0")
{
values[i] = "r0,r1";
}
}
// And finally, turn your object back into a json string
var result = JsonConvert.SerializeObject(jobject);
And this is the final result:
{
"properties":{
"displayName":"jayatestdefid",
"description":"test assignment through API",
"metadata":{
"assignedBy":"xyz#gmail.com"
},
"policyDefinitionId":"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters":{
"ringValue":{
"value":[
"r0,r1"
]
}
},
"enforcementMode":"DoNotEnforce"
}
}

serializing nested json c#

Big apologies for the long post. I need to create the below json format for a post to rest api in c#. The below call works and I have used successfully in Postman to add it to the target system.
{
"item": {
"attrs": {
"attr": [{
"name": "IP_Category",
"value": "Miscellaneous"
}, {
"name": "Description",
"value": "Picture of Rabbit"
}, {
"name": "Title",
"value": "A Rabbit"
}
]
},
"resrs": {
"res": [{
"filename": "Rabbit.jpg",
"base64": "/9j/4AAQSkZJR"
}
]
},
"acl": {
"name": "Submitter"
},
"entityName": "IP_Document"
}
}
Based on the research I've done I need to copy and "paste special" into a new class file in visual studio so it can create the class objects based on the json format (Pretty cool!). And this is what it creates:
namespace BasicWebApp
{
public class Rootobject
{
public Item item { get; set; }
}
public class Item
{
public Attrs attrs { get; set; }
public Resrs resrs { get; set; }
public Acl acl { get; set; }
public string entityName { get; set; }
}
public class Attrs
{
public Attr[] attr { get; set; }
}
public class Attr
{
public string name { get; set; }
public string value { get; set; }
}
public class Resrs
{
public Re[] res { get; set; }
}
public class Re
{
public string filename { get; set; }
public string base64 { get; set; }
}
public class Acl
{
public string name { get; set; }
}
}
Problem 1: Why is vs renaming the res json object to to class Re? Is it a reserved word in c#?
Problem 2: I know I have to nest things in this fashion but I two levels deep and not sure what to code?
var model = new Rootobject();
model.item = new Item
{
attrs = new Attrs
{
attr = new List<Attr>
{
**now what??**
}
}
}
Don't have answer to your first question yet(but looking for it):
For your second question, at now what part you just do:
new Attr(){ name = "name1", value = "value1" },
new Attr(){ name = "name1", value = "value2" }
But that's not what i advise. I advise you to have your Attr collection ready then assign it. Like:
var model = new Rootobject();
model.item = new Item
{
attrs = yourAttrCollection
}
It also goes for everyting else you do. Have your stuff ready, then assign them. It increases readability in nested objects.
Problem 1: Why is vs renaming the res json object to to class Re? Is it a reserved word in c#?
No Re is not reserved word in class.
As mentioned by TheGeneral
res is plural for re's
You can use JsonProperty attribute to resolve this issue like
public class Resrs
{
[JsonProperty("res")]
public Re[] res { get; set; }
}
Problem 2: I know I have to nest things in this fashion but I two levels deep and not sure what to code?
var model = new Rootobject();
model.item = new Item
{
attrs = new Attrs
{
attr = new List<Attr>
{
new Attr { name = "abc", value = "ABC" },
new Attr { name = "pqr", value = "PQR" }
}
}
}
Thanks to all that responded. It helped. I ended up using the below code to create the json object I needed.
var model = new RootObject();
model.item = new Item
{
attrs = new Attrs
{
attr = new List<Attr>
{
new Attr { name = "IP_Category", value = ddlContent.Text },
new Attr { name = "Description", value = txtDesc.Text },
new Attr { name = "Title", value = txtTitle.Text }
}
},
resrs = new Resrs
{
res = new List<Re>
{
new Re { filename = fName, base64 = base64string},
}
},
acl = new Acl
{
name = "Submitter"
},
entityName = "IP_Document"
};

c# Converting json string with list of objects to a c# object

I'm tring to convert a string json to c# object,
I've already read several replies in here regarding to similar questions but none of the solutions worked.
This is the json obj
{
"Customer": {
"data_0": {
"id": "273714",
"FirstName": "Zuzana",
"LastName": "Martinkova"
},
"data_1": {
"id": "274581",
"FirstName": "Ricardo",
"LastName": "Lambrechts"
},
"data_2": {
"id": "275190",
"FirstName": "Daniel",
"LastName": "Mojapelo"
},
"data_3": {
"id": "278031",
"FirstName": "Sulochana",
"LastName": "Chandran"
}
}
}
I created the following objects according to the json obj
public class Customer
{
public List<Data> Customers{ get; set; }
public Customer()
{
Customers = new List<Data>();
}
}
public class Data
{
public string id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
As for my code I made a small console app example with all the solotions I found here
static void Main(string[] args)
{
try
{
string jsonString = File.ReadAllText(ConfigurationSettings.AppSettings["filepath"].ToString());
//solution 1
JObject jsonone = JObject.Parse(jsonString);
var collection_one = jsonone.ToObject<Customer>();
//solution 2
JavaScriptSerializer serializer = new JavaScriptSerializer();
var collection_two = serializer.Deserialize<Customer>(jsonString);
//solution 2
var collection_three = JsonConvert.DeserializeObject<Customer> (jsonString);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message); ;
}
Console.ReadKey();
}
Ths json string I get from a 3rd party webservice so just for the example I'm reading the json from a txt file,
the jsonString param value after reading is:
"{\"Customer\":{\"data_0\":{\"id\":\"273714\",\"FirstName\":\"Zuzana\",\"LastName\":\"Martinkova\"},\"data_1\":{\"id\":\"274581\",\"FirstName\":\"Ricardo\",\"LastName\":\"Lambrechts\"},\"data_2\":{\"id\":\"275190\",\"FirstName\":\"Daniel\",\"LastName\":\"Mojapelo\"},\"data_3\":{\"id\":\"278031\",\"FirstName\":\"Sulochana\",\"LastName\":\"Chandran\"}}}"
On every solution I make the collections count is 0, data objects are not including inside the list.
Can someone put some light on it and tell me what is wrong?
Thanks in advance
Your JSON is a Dictionary<string, Data>, not a List<Data>. In addition to that your property is called "Customer", not "Customers". To solve this you need to change a couple things:
public class Customer
{
//JsonProperty is Used to serialize as a different property then your property name
[JsonProperty(PropertyName = "Customer")]
public Dictionary<string, Data> CustomerDictionary { get; set; }
}
public class Data
{
public string Id { get; set; } //You should make this "Id" not "id"
public string FirstName { get; set; }
public string LastName { get; set; }
}
With these class definitions you can easily use the JsonConvert.DeserializeObject() and JsonConvert.SerializeObject() methods:
Customer customer = JsonConvert.DeserializeObject<Customer>(json);
string newJson = JsonConvert.SerializeObject(customer);
I made a fiddle here to demonstrate.
You can try this one.
Add empty class
public class Customer : Dictionary<string, Data>{} //empty class
And the update your existing code
//solution 1
JObject jsonone = JObject.Parse(jsonString);
//Add this line
var token = jsonone.SelectToken("Customer").ToString();
//solution 2 - update jsonString to token variable created above.
var collection_three = JsonConvert.DeserializeObject<Customer>(token);

C# Json Parse with Newtonsoft.Json

MY JSON
{"Players": [{"UserId": "76561198160689142"},{"UserId": "76561198160689123"},{"UserId": "76561198160689145"},{"UserId": "76561198160689144"}]}
and i'm sucess on Deserialize
JsonOxide obj = JsonConvert.DeserializeObject<JsonOxide>(jsonread);
foreach(var item in obj.Players)
{
MessageBox.Show(item.UserId);
}
class JsonOxide.cs (i'm use json2csharp to make code)
public class Player
{
public string UserId { get; set; }
}
public class JsonOxide
{
public List<Player> Players { get; set; }
}
I Want Serialize my Listview Item so i try like this code but i don't know
how to serialize
List<JsonOxide> jolist = new List<JsonOxide>();
var objs = new Object[]
{
//wrong code
}
JsonOxide jo = new JsonOxide();
listivew item exmaple
listivewitem 1.text = "test"
listviewitem 2.text = "test2"
will be save { "userid": "test"},{ "userid": "test2"}
and
if Listviewitem 1 is removed will edit json
delete userid:test value how to do this?
You can use the SerializeObject method.
string players = JsonConvert.SerializeObject(oxide);
As a full example for the structure you have provided:
JsonOxide oxide = new JsonOxide();
oxide.Players = new List<Player>();
oxide.Players.Add(new Player { UserId = "1" });
oxide.Players.Add(new Player { UserId = "2" });
string players = JsonConvert.SerializeObject(oxide);
Console.WriteLine(players);
Would display:
{"Players":[{"UserId":"1"},{"UserId":"2"}]}

Categories

Resources