How do I make a JSON array? - c#

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.

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

Parsing json file in c# to get into all sections and properties

==========Update
So in trying to phrase the issue properly, I have misled the responders in not giving me the answer I need. Apologies, let me try to clarify.
I need to be able to cycle through a json file that is not as structured as I indicated in the OP, it is much more random. The OP file did not convey that very well.
Let me try to describe what is closer to the file I'll be getting. The first two levels will be fixed, I'll call them LevelA and LevelB. But the properties in LevelB can be any pair of random data. This is a better json file example:
{
"LevelA": {
"LevelB": [
{
"EmpName": "John",
"EmpGender": "Male",
"Age": "25"
},
{
"FavoriteFood": "Beer",
"BaseballTeam": "Kansas City Royals"
},
{
"Red": "10",
"Blue": "40",
"White: "True"
}
]
}
}
Say I need to write out the following to console:
A LevelB entry has these properties:
Property: EmpName, Value: John
Property: EmpGender, Value: Male
Property: Age, Value: 25
A LevelB entry has these properties:
Property: FavoriteFood, Value: Beer
Property: BaseballTeam, Value: Kansas City Royals
A LevelB entry has these properties:
Property: Red, Value: 10
Property: Blue, Value: 40
Property: White, Value: True
It may not make sense but, I need to find a way to do that, I need that knowledge. I appreciate the answers about using a model, but I don't see a way to use a model without complicating what I think should be a simple task. Although not simple enough for me to figure out apparently. :)
==========
C#, VS 2019, a .NET framework console test app. I'm looking to do something simple but I can't find the right syntax.
I have a json file with the following structure. I want to loop through each Employee below and get at its properties (name, gender, etc...):
{
"Company": {
"Employees": [
{
"EmpName": "John",
"EmpGender": "Male",
"Age": "25"
},
{
"EmpName": "Mary",
"EmpGender": "Female"
},
{
"EmpName": "Bill",
"Age": "30"
}
]
}
}
First question is which package will do the job? I've installed Microsoft.Extensions.Configuration.Json and System.Configuration.ConfigurationManager but am having difficulties getting the syntax correct. Are these the right packages to use? I decided to use those because I thought I could load the file via ConfigurationBuilder and that the GetSection and/or GetChildren methods would help me. I can load the file but I can't figure out how to use those methods to give me what I want.
Second I don't want to build a model for this, I just want at the data. If I can get each employee into a dictionary, I can analyze that, and that would get me going. Thanks for any advice.
You can use the built-in JSON library in the .net core
using System.Text.Json;
add the following model definition
public class Rootobject
{
public Company Company { get; set; }
}
public class Company
{
public Employee[] Employees { get; set; }
}
public class Employee
{
public string EmpName { get; set; }
public string EmpGender { get; set; }
public string Age { get; set; }
}
deserialize your object like the following
string jsonData = File.ReadAllText("data.json");
Rootobject ob = JsonSerializer.Deserialize<Rootobject>(jsonData);
now you have ob in you c# represent your JSON as C# object
I don't want to build a model for this
if you use Visual Studio you can auto generate your model classes required for your JSON as described here the above models are auto generated by Visual Studio
If you don't want to create a model,and get a List<Dictionary<string,string>>,you can use custom model binding,here is a demo:
CustomBinder:
public class CustomBinder:IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model = new List<Dictionary<string, string>>();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);
var s = mydata["Company"]["Employees"].ToString();
var list=JsonConvert.DeserializeObject<List<JObject>>(s);
foreach (var jobj in list) {
Dictionary<string, string> d = new Dictionary<string, string>();
foreach (var x in jobj)
{
string name = x.Key;
string value = x.Value.ToString();
d.Add(x.Key, x.Value.ToString());
}
model.Add(d);
}
}
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
Action:
public void TestJson1([ModelBinder(BinderType = typeof(CustomBinder))] List<Dictionary<string, string>> jsondata)
{
}
result:
Why is it a requirement not to build models? In my opinoin that is the easiest way and if you need to expand due to JSON changes, you can easily adapt it in the code. I paste a sample code here what is using System.Text.Json namespace (no other packages are also required due to it is built-in).
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace jsontest
{
class Program
{
static void Main(string[] args)
{
string input = "{ \"Company\": { \"Employees\": [{ \"EmpName\": \"John\", \"EmpGender\": \"Male\", \"Age\": \"25\" }, { \"EmpName\": \"Mary\", \"EmpGender\": \"Female\" }, { \"EmpName\": \"Bill\", \"Age\": \"30\" }]}}";
var processedInput = JsonSerializer.Deserialize<Company>(input);
foreach (var item in processedInput.Peoples.PeopleList)
{
Console.WriteLine($"{item.Name} - {item.Gender} - {item.Age}");
}
}
}
public class Employee
{
[JsonPropertyName("EmpName")]
public string Name { get; set; }
[JsonPropertyName("EmpGender")]
public string Gender { get; set; }
[JsonPropertyName("Age")]
public string Age { get; set; }
}
public class Employees
{
[JsonPropertyName("Employees")]
public List<Employee> PeopleList { get; set; }
}
public class Company
{
[JsonPropertyName("Company")]
public Employees Peoples { get; set; }
}
}
Update after your update:
Strange why you store data in JSON on this way. I wrote a quick code, it is using regex and some built-in function to parse the text. At the end result is similar what you would prefer. Code is a bit long, but only because I put some comment to make understanding easier.
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace jsontest
{
class Program
{
static void Main(string[] args)
{
List<List<ListItem>> result = new List<List<ListItem>>();
string input = "{ \"Company\": { \"Employees\": [{ \"EmpName\": \"John\", \"EmpGender\": \"Male\", \"Age\": \"25\" }, { \"EmpName\": \"Mary\", \"EmpGender\": \"Female\" }, { \"EmpName\": \"Bill\", \"Age\": \"30\" }]}}";
// Remove new lines, so input will become one single line
input = input.Replace(Environment.NewLine, " ");
// 1. group is the group name (in this case Employees)
// 2. group is the content after group name
string pattern1 = #"[{].+[{](.+)[\[](.+)[\]]";
foreach (System.Text.RegularExpressions.Match m in System.Text.RegularExpressions.Regex.Matches(input, pattern1))
{
// groupName -> "Employees":
string groupName = m.Groups[1].Value;
// groupName -> Employees
groupName = groupName.Substring(0, groupName.LastIndexOf("\""));
groupName = groupName.Substring(groupName.IndexOf("\"") + 1);
// contentList -> { "EmpName": "John", "EmpGender": "Male", "Age": "25" }, { "EmpName": "Mary", "EmpGender": "Female" }, { "EmpName": "Bill", "Age": "30" }
string contentList = m.Groups[2].Value;
// Split the line onto more lines where "}," characters
// { "EmpName": "John", "EmpGender": "Male", "Age": "25"
// { "EmpName": "Mary", "EmpGender": "Female"
// { "EmpName": "Bill", "Age": "30" }
string[] contentItems = contentList.Split("},");
foreach (var item in contentItems)
{
// Check every group and store them in separate list
result.Add(new List<ListItem>());
string[] keys = item.Split(",");
foreach (var key in keys)
{
// Check every Key-Value pair and store their value in the current list
string pattern2 = "[\"](.+)[:].[\"](.+)[\"]";
foreach (System.Text.RegularExpressions.Match m2 in System.Text.RegularExpressions.Regex.Matches(key, pattern2))
{
result[result.Count - 1].Add(new ListItem() { Property = groupName, Key = m2.Groups[1].Value.Substring(0, m2.Groups[1].Value.Length - 1), Value = m2.Groups[2].Value });
}
}
}
}
for (int i = 0; i < result.Count; i++)
{
for (int j = 0; j < result[i].Count; j++)
{
if (j == 0)
Console.WriteLine($"A {result[i][j].Property} entry has these properties:");
Console.WriteLine($"Proprty: {result[i][j].Key}, Value: {result[i][j].Value}");
}
}
}
}
class ListItem
{
public string Property { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
}
Output of this code is:
A Employees entry has these properties:
Proprty: EmpName, Value: John
Proprty: EmpGender, Value: Male
Proprty: Age, Value: 25
A Employees entry has these properties:
Proprty: EmpName, Value: Mary
Proprty: EmpGender, Value: Female
A Employees entry has these properties:
Proprty: EmpName, Value: Bill
Proprty: Age, Value: 30

Convert json string from one type to another with .net core c#

I am struggling to convert below input json to output json as this is what is the required format to call
hubspot api to submit a form. I am writing this using .net core within Azure function.
Input Json
{
"Email":"myemail#test.com",
"Phone":"12345678",
"Address":"address 1"
}
Output json
{
"fields": [
{
"name": "Email",
"value": "myemail#test.com"
},
{
"name": "Phone",
"value": "12345678"
},
{
"name": "Address",
"value": "address 1"
}
]
}
I converted the input json to dictionary using
IDictionary<string, string> dictionary = JsonConvert.DeserializeObject<IDictionary<string, string>>(inputJson);
but that gives me key value pair instead of name value pair.
I would like the output as detailed above.
Any help/example code would be highly appreciated.
You could create your own "NameValuePair" class/struct if you don't want "Key" as the field name:
public class FieldContainer
{
[JsonProperty("fields")]
public IEnumerable<NameValuePair> Fields { get; set; }
}
public struct NameValuePair
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
public NameValuePair(string name, string value)
{
Name = name;
Value = value;
}
}
And then do like you've already done, but converting the KeyValuePairs into your own struct:
var inJson = #"{
""Email"":""myemail#test.com"",
""Phone"":""12345678"",
""Address"":""address 1""
}";
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(inJson);
var container = new FieldContainer
{
Fields = dict.Select(pair => new NameValuePair(pair.Key, pair.Value))
};
var outJson = JsonConvert.SerializeObject(container);
See this fiddle for a demonstration.
Easiest way to do this would be to take the json and convert it to Dictionary<string, string>. Loop over each KeyValuePair and create a list of Fields using LINQ. Once you have the List of fields, create your RootObject.
public class RootObject
{
[JsonProperty("fields")]
public List<Field> Fields { get; set; }
}
public class Field
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("value")]
public string Value { get; set; }
}
// Create a dictionary
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonStr);
// Create a list of Fields
List<Field> fields = dict.Select(x => new Field() { Name = x.Key, Value = x.Value }).ToList();
// Create the final Object.
RootObject rootObj = JsonConvert.SerializeObject(new RootObject() { Fields = fields });
Alternative solution, using JObject.Parse() to parse the original JSON, then iterate its Properties to create an array of JObjects with different names and values.
The resulting IEnumerable<JObject> is then converted to a JArray, used to create the final fields object.
var jObj = JObject.Parse(json);
var newObjects = jObj.Properties().Select(p => new JObject {
new JProperty("name", p.Name),
new JProperty("value", p.Value)});
var fields = new JObject() {
{ "fields", JArray.FromObject(newObjects)}
};
Console.WriteLine(fields);

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

Loading data from JSON file for one time

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).

Categories

Resources