I have a json file which has some hundereds of rows stored like below..
[
{
"Id": "1",
"Name": "A"
},
{
"Id": "2",
"Name": "B"
}
]
I am trying to load this into collection of a class. This data is static and wont change, so I need to load this only once.
I have created a class and loading this in private constructor and loading into collection that I have in the class.
public sealed class JsonLoader : IJsonloader
{
private readonly IEnumerable<Product> products = new List<Product>();
private JsonLoader()
{
using (var r = new StreamReader("data.json"))
{
var json = r.ReadToEnd();
products = //deserialse the json here
}
}
public static IEnumerable<Product> Products => this.products;
}
Implement singleton using structure map singleton option. I want to know if my way of implementation is correct or if this can improved any further?
or Any other best way to do it? any help much appreciated :)
Ok, so i done example that taking string of json object Deserialize it and create Product object and add it to Product
list
public class Program
{
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
}
static void Main(string[] args)
{
IList<Product> productList = new List<Product>();
string json = "{\"Id\": 1, \"Name\": \"A\"},{\"Id\": 2, \"Name\": \"B\"}";
string[] jsonArray = json.Split(new string[] { "},{" }, StringSplitOptions.None);
foreach (string j in jsonArray)
{
string jsonTemp = j.Replace("{", "").Replace("}", "");
string myJson = "{" + jsonTemp + "}";
productList.Add(JsonConvert.DeserializeObject<Product>(myJson));
}
}
}
Output:
you will have 2 objects in product list.
I made it in Main for example, you can take it to external function that gets string as parameter and returns list of users (it will be most correct).
Related
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"
}
}
I want many of them but I don't how to make so many I can only make one just like this here:
[
{
"NAME1": "Max1"
}
]
But I want to make this:
[
{
"NAME1": "Max1"
},
{
"NAME2": "Max2"
},
{
"NAME3": "Max3"
},
{
"NAME4": "Max4"
}
]
How do I do it
Here is my code:
public void nxt_Click(object sender, EventArgs e)
{
List<Voc> _data = new List<Voc>();
_data.Add(new Voc()
{
NAME = textBox1.Text
});
string jger2 = JsonConvert.SerializeObject(_data.ToArray(), Formatting.Indented);
File.WriteAllText(#"D:\Users\Oxygen\Desktop\ss.json", jger2);
}
public class Voc
{
public string NAME { get; set; }
}
has anybody any ideas?
Below are a couple of ways to do this, demonstrated in this fiddle.
The first uses anonymous types, which are objects which don't have a real class, but are constructed by assigning values to properties. However, to use these you need to know the property names at compile time; so this will only work if you know exactly how many names you'll have in your array. e.g.
var data = new object[] {
new {Name1 = textBox1.Text}
,new {Name2 = textBox2.Text}
,new {Name3 = textBox3.Text}
,new {Name4 = textBox4.Text}
};
Another approach is to use a dictionary, which can be populated with name value pairs at runtime, then you can convert these to JSON. E.g.
var textBoxes = new [] {textBox1, textBox2, textBox3, textBox4};
var dict = new Dictionary<string,string>();
for (var i = 0; i< textBoxes.Length; i++)
{
dict.Add(string.Format("Name{0}", i), textBoxes[i].Text );
}
However
I would strongly advise against these methods; or rather this approach. JSON is designed to be made up of key-value pairs. They keys should be known, whilst the values can change. That means that if you have 4 different values for a name instead of holding 4 different names, you hold those values against that name; e.g.
{"Name": ["Max1","Max2","Max3","Max4"]}
...with the number of the element being defined by the array's index.
The C# for that looks like this:
SomeClass data = GetValues();
//...
public class SomeClass
{
public IEnumerable<string> Name {get;private set;}
//or: public string[] Name {get;private set;}
//...
}
If you really need to store the different names, those should be stored as values against the name key; e.g.
[
{"Name": "Name1", "Value": "Max1"}
,{"Name": "Name2", "Value": "Max2"}
,{"Name": "Name3", "Value": "Max3"}
,{"Name": "Name4", "Value": "Max4"}
]
The C# for that looks like this:
IEnumerable<SomeClass> data = GetValues();
//or: SomeClass[] data = GetValues();
//...
public class SomeClass
{
public string Name {get;private set;}
public string Value {get;private set;}
//...
}
Full Code
using System;
using System.Linq;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
//setup our test data
var textBox1 = new TextBox("Max1");
var textBox2 = new TextBox("Max2");
var textBox3 = new TextBox("Max3");
var textBox4 = new TextBox("Max4");
//demo using anonymous objects (NB: property names must be known at compile time)
var data = new object[] {
new {Name1 = textBox1.Text}
,new {Name2 = textBox2.Text}
,new {Name3 = textBox3.Text}
,new {Name4 = textBox4.Text}
};
Console.WriteLine( JsonConvert.SerializeObject(data, Formatting.Indented));
//demo using a dictionary
var textBoxes = new [] {textBox1, textBox2, textBox3, textBox4};
var dict = new Dictionary<string,string>();
for (var i = 0; i< textBoxes.Length; i++)
{
dict.Add(string.Format("Name{0}", i+1), textBoxes[i].Text );
}
Console.WriteLine("[" + string.Join(",", dict.Select( e => string.Format("{{\"{0}\": \"{1}\"}}", e.Key.Replace("\"","\"\""), e.Value.Replace("\"","\"\"") ) )) + "]"); //based on https://stackoverflow.com/questions/5597349/how-do-i-convert-a-dictionary-to-a-json-string-in-c/5597628#5597628
}
}
//dummy class
public class TextBox
{
public TextBox(string text){Text = text;}
public string Text{get;private set;}
}
First of all, your Array is poorly formatted.
It should be:
{
"NAMES": [
{
"NAME": "Max1"
},
{
"NAME": "Max2"
},
{
"NAME": "Max3"
},
{
"NAME": "Max4"
}
]
}
Run that through json2Csharp.com and it will generate the following:
public class NAME
{
public string NAME { get; set; }
}
public class RootObject //Rename this
{
public List<NAME> NAMES { get; set; }
}
Which you should be able to serialize and deserialize using almost any C# JSON library.
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);
I have JSON:
{
"One": [
{
"ID": 1,
"name": "s"
},
{
"categoryID": 2,
"name": "c"
}
],
"Two": [
{
"ID": 3,
"name": "l"
}
],
"Three": [
{
"ID": 8,
"name": "s&P"
},
{
"ID": 52,
"name": "BB"
}
]
}
I want to:
Take this JSON to any object(like JObject)
Filter the JSON on different conditions(like name start with s, etc
Return this JSON to client
Things I have tried:
1. Creating models:
class Model
{
public int Id;
public string name;
}
class MainModel
{
public string mainName;
public List<Model> categories;
}
And use these model to:
List<MainModel> m = json_serializer.DeserializeObject(jsonString);
I tried to Dictionary also but getting unable to cast exception.
any help would be appreciated.
The following will allow you to deserialize your JSON to a Dictionary and filter on it. This uses Newtonsoft.Json Nuget package, but that's fairly common. Code posted below. Working example found here .Net Fiddle.
using System;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var json = "{\"One\": [{ \"ID\": 1, \"name\": \"s\"},{ \"categoryID\": 2, \"name\": \"c\"}],\"Two\": [{ \"ID\": 3, \"name\": \"l\"}],\"Three\": [{ \"ID\": 8, \"name\": \"s&P\"},{ \"ID\": 52, \"name\": \"BB\"}]}";
var deserialized = JsonConvert.DeserializeObject<Dictionary<string, List<Model>>>(json);
Console.WriteLine(deserialized["One"][0].name);
Console.WriteLine("Filter to starts with s");
var filtered = deserialized.SelectMany(item => item.Value).Where(innerItem => innerItem.name.StartsWith("s"));
foreach(var item in filtered){
Console.WriteLine(item.name);
}
}
public class Model{
public int ID {get;set;}
public string name {get;set;}
public int categoryID {get;set;}
}
}
I have written this code assuming that:
One, Two and Three are a MainCategory -which is seralized as JProperty from a KeyValuePair<string name, List<SubCategory> values>. Long type name, eh? Add the following if you want to use the result dictionary often:
using MainCategories = System.Collections.Generic.Dictionary<string, System.Collections.Generic.List<JsonDeSerializtionTest.SubCategory>>;
categoryID and ID are properties that descibe an Id and can not co-exist on the same SubCategory but do change the type of SubCategory.
1. Create the SubCategory class:
public class SubCategory
{
[JsonIgnore]
public DataTypes DataType { get; set; }
[JsonIgnore]
public string Parent { get; set; }
[JsonProperty("ID")]
public int Id { get; set; }
[JsonProperty("categoryID")]
public int CategoryId => Id;
[JsonProperty("name")]
public string Name { get; set; }
public bool ShouldSerializeId()
{
return DataType == DataTypes.Id;
}
public bool ShouldSerializeCategoryId()
{
return DataType == DataTypes.CategoryId;
}
}
2. Create the Deserialize(string json) function:
private static MainCategories Deserialize(string json)
{
Dictionary<string, List < SubCategory >> jsonBody = new Dictionary<string, List<SubCategory>>();
JObject jObject = JObject.Parse(json);
// the outer object {one...two..}
foreach (KeyValuePair<string, JToken> jMainCategory in jObject)
{
// jMainCategory => "one": [{...}, {...}]
string key = jMainCategory.Key;
List<SubCategory> values = new List<SubCategory>();
foreach (JObject jSubCategory in jMainCategory.Value)
{
//jsubCategory => {"name" : ..., "ID": ... }
SubCategory subCategory = new SubCategory();
JToken idProperty;
if (jSubCategory.TryGetValue("ID", out idProperty))
{
subCategory.DataType = DataTypes.Id;
subCategory.Id = idProperty.Value<int>();
}
else
{
subCategory.DataType = DataTypes.CategoryId;
subCategory.Id = jSubCategory["categoryID"].Value<int>();
}
subCategory.Name = jSubCategory["name"].Value<string>();
subCategory.Parent = key;
// subCategory.AnotherProperty = jSubCategory["anotherproperty"].Value<type>();
values.Add(subCategory);
}
jsonBody.Add(key, values);
}
return jsonBody;
}
3. Use the function to get a Dictionary<string, List<SubCategory>> which you can use for sorting and filtering. Example:
public static MainCategories WhereNameStartsWith(this MainCategories jsonBody, string str)
{
MainCategories result = new MainCategories();
//if you want to keep the result json structure `as is` return a MainCategories object
foreach (var subCategory in jsonBody.SelectMany(mainCategory => mainCategory.Value).Where(subCategory => subCategory.Name.StartsWith(str)))
{
if(result.ContainsKey(subCategory.Parent))
result[subCategory.Parent].Add(subCategory);
else
result.Add(subCategory.Parent, new List<SubCategory> {subCategory});
}
// if you just want the subcategories matching the condition create a WhereListNameStartsWith method
// where `result` is a list of subcategories matching the condition
return result;
}
Upside:
No playing around with NewtonSoft JsonConverter or ContractResolvers.
The ability to use LINQ to easily sort Name AND CategoryId/Id which have the same value but make a different SubCategory.DataType:
foreach (var subCategory in jsonBody.SelectMany(mainCategory => mainCategory.Value).Where(subCategory => subCategory.DataType == DataTypes.CategoryId))
You can easily serialize the JSON back to string representation. Example:
string jsonIn ="{\"One\":[{\"ID\":1,\"name\":\"s\"}," +
"{\"categoryID\":2,\"name\":\"c\"}]," +
"\"Two\":[{\"ID\":3,\"name\":\"l\"}]," +
"\"Three\":[{\"ID\":8,\"name\":\"s&P\"}," +
"{\"ID\":52,\"name\":\"BB\"}]}";
MainCategories desrializedJson = Deserialize(jsonIn);
MainCategories filtered = desrializedJson.WhereNameStartsWith("s");
string jsonOut = JsonConvert.SerializeObject(desrializedJson, Formatting.None);
Debug.Assert(jsonOut == jsonIn); //true
Removes the need for null checking when accessing Id/CategoryId.
My favorite: using C# syntax for property names.
Downside:
I don't know. This is a paste and forget soltuion :P
Probably a harder time when changing your JSON structure (although I might argue it would make things much easier for you)
Notes:
Parent is optional and is used to make things easier when using LINQ
DataTypes is an enum which is used to determine wether ID or categoryID was found if you want such information and also to serialize the proper property (identical two way convertion)
public enum DataTypes
{
Id,
CategoryId
};
Hi I'm trying to parse a JSON page in C#, but I can't seem to read some strings, like:
"versions": [
{
"date": 1340466559,
"dl_link": "http://dev.bukkit.org/media/files/599/534/NoSwear.jar",
"filename": "NoSwear.jar",
"game_builds": [
"CB 1.2.5-R4.0"
],
"hard_dependencies": [],
"md5": "d0ce03e817ede87a9f76f7dfa67a64cb",
"name": "NoSwear v5.1",
"soft_dependencies": [],
"status": "Semi-normal",
"type": "Release"
},
How could I read that?
This is the code I have right now and works for everything else except this:
public static void GetMoreInfo(string plugin)
{
try
{
string url = "http://bukget.org/api/plugin/";
var wc = new WebClient();
var json = wc.DownloadString(url + plugin);
var moreInfo = JsonConvert.DeserializeObject<MoreInfo>(json);
foreach (var category in moreInfo.categories)
{
Categories += category + ", ";
}
Categories = Categories.Remove(Categories.Length - 2, 2);
}
catch (Exception)
{
}
finally
{
if (string.IsNullOrEmpty(Categories))
{
Categories = "No data found.";
}
}
}
public class MoreInfo
{
public string[] categories;
}
How about handling your json dynamically, instead of deserializing to a concrete class?
var wc = new WebClient();
var json = wc.DownloadString("http://bukget.org/api/plugin/test");
dynamic moreInfo = JsonConvert.DeserializeObject(json);
Console.WriteLine("{0} {1} {2}", moreInfo.name, moreInfo.desc, moreInfo.status);
string categories = String.Join(",", moreInfo.categories);
Console.WriteLine(categories);
Or would you prefer the classical approach?
var plugin = JsonConvert.DeserializeObject<Plugin>(json);
string categories = String.Join(",",plugin.categories);
public class Plugin
{
public List<string> authors;
public string bukkitdev_link;
public List<string> categories;
public string desc;
public string name;
public string plugin_name;
public string status;
public List<Version> versions;
}
public class Version
{
public string date;
public string filename;
public string name;
//.......
}
I could be wrong, but the JSON you're receiving is an array named versions but you're trying to deserialize it into a MoreInfo object that exposes an array named categories (unless it's just a typo in your example). Have you tried renaming MoreInfo.categories to MoreInfo.versions?
UPDATE
I don't think that would make a difference because the JSON converter doesn't know what to do with each object in the array. You need to provide an object to deserialize each element in the JSON array.
For example, try modifying the MoreInfo object to include matching properties to the JSON string (the elements in the array)
[DataContract]
public class MoreInfo
{
[DataMember]
public DateTime date { get; set; }
[DataMember]
public string dl_link { get; set; }
...
}
And then try to deserialize the JSON string to a List<MoreInfo>:
JsonConverter.DeserializeObject<List<MoreInfo>>(json)
You will then have to modify the rest of your code to work with MoreInfo objects and not strings in an array.
REFER TO THIS ANSWER
See this question, the accepted answer should help you solve your problem: Json.NET: Deserialization with list of objects