How to parse unknown Json file with Json.net in C# - c#

I'm able to get a dynamic Json object using
dynamic obj = JsonConvert.DeserializeObject(json);
It seems to be a nested object structure
I need to graph every variable in the json file, but the json file structure changes often
Is there a way to parse through this structure using nested foreach() statements?
If not, can can I parse it by accessing each element via a string like a Dictionary?
for example something like:
if(obj["Item1"]["Parameter3"]["Value2"]` != NULL)
int number = obj["Item1"]["Parameter3"]["Value2"]`
Thanks,

Yes there is an API for querying dynamically.
See the documentation here: https://www.newtonsoft.com/json/help/html/QueryingLINQtoJSON.htm
Code looks something like this:
JObject rss = JObject.Parse(json);
var postTitles =
from p in rss["channel"]["item"]
select (string)p["title"];

Finally figured this api out
Some JToken entries have a list of values, others have a name and value. You have to sort which one is which prior to parsing it.
This will create a Dictionary with every entry in the Json file
void SomeFunction()
{
Dictionary<string, decimal> json_data = new Dictionary<string, decimal>();
dynamic json_obj = JsonConvert.DeserializeObject(json);
Linearize(ref json_data, json_obj);
}
void Linearize(ref Dictionary<string, decimal> input_dict, JToken json_data, string key = "")
{
int i;
if (json_data != null)
{
if (json_data.HasValues)
{
i = 0;
foreach (dynamic entry in json_data)
{
//Add a Name field if it exists
Type typeOfDynamic = entry.GetType();
if (typeOfDynamic.GetProperties().Where(p => p.Name.Equals("Name")).Any())
key += entry.Name + ".";
//If JToken is an Array
if (((JToken)entry).HasValues)
{
Linearize(ref input_dict, entry, key + "[" + i++ + "]" + ".");
}
//If JToken is a data type
else if (entry.Type == JTokenType.String || entry.Type == JTokenType.Float || entry.Type == JTokenType.Integer)
{
decimal output;
if (decimal.TryParse(entry.ToString(), out output))
input_dict.Add(key + "[" + i++ + "]", output);
}
}
}
}
}

Related

Using JArray.Parse(json) on an associative array

I've put together the following code from this answer:
JArray jsonArray = JArray.Parse(json);
foreach(JObject jsonObject in jsonArray.Children<JObject>())
{
foreach(JProperty jProperty in jsonObject.Properties())
{
int id = jProperty.id;
string name = (string)jProperty.Name;
textBox1.AppendText(id.ToString() + " // " + name + Environment.NewLine);
}
}
A sample of the JSON I'm trying to parse is as following:
[{"id":"219","name":"Jimmy"},{"id":"220","name":"Bobby"},{"id":"218","name":"Arthur"}]
The answer I referenced deals with parsing key => value pairs, how can I parse an associative array?
JSON doesn't have "associative arrays". It has arrays and objects.
What you have here is an array of objects. So, JArray.Parse will give you a JArray, and each item in it is itself a JObject:
var array = JArray.Parse(json);
foreach(JObject obj in array)
{
int id = obj.Value<int>("id");
string name = obj.Value<string>("name");
// ...
}

Creating a csv file from json with different header values per record

I have a massive json file that is very nested. I need to write the multiple csv files depending on the name of a certain field, if it exists then add the values to the headers I've created if it does not then create a new one. This is working just fine. However I have ran into a problem where the headers do not match because this particular header doesn't exist for that record. Example:
Header: Dog Cat Mouse Horse
Record1: yes yes yes yes
// above is an example of a file with all values
Adding record Two where a header value is not listed at all
Header: Dog Cat Mouse Horse
Record1: yes yes yes yes
Record2: yes yes yes ***
Record2 above does not have a mouse on the record but because it doesn't line up the yes shifted left. I need to write a Null under than header before spitting out the values to the file. Below is my code if you could help that would be great as I'm lost at this point:
static List<string> headList = new List<string>();
static List<string> newHeaderList = new List<string>();
static List<string> valueList = new List<string>();
static List<string> oldHeadList = new List<string>();
static void Main()
{
var data = JsonConvert.DeserializeObject<dynamic>(File.ReadAllText(
#"C:\Users\nphillips\workspace\2016R23\UITestAutomation\SeedDataGenerator\src\staticresources\seeddata.resource"));
string fileName = "";
var bundles = data.RecordSetBundles;
foreach (var bundle in bundles)
{
var records = bundle.Records;
foreach (var record in records)
{
var test = record.attributes;
foreach (var testagain in test)
{
// Getting the object Name Ex. Location, Item, etc.
var jprop = testagain as JProperty;
if (jprop != null)
{
fileName = jprop.First.ToString().Split('_')[2] + ".csv";
}
break;
}
string header = "";
string value = "";
foreach (var child in record)
{
var theChild = child as JProperty;
if (theChild != null && !theChild.Name.Equals("attributes"))
{
// adding the name and values to list
headList.Add(child.Name);
valueList.Add(child.Value.ToString());
}
}
// calling method to write columns and values
writeCSV(headList, valueList, fileName);
valueList.Clear();
headList.Clear();
}
}
}
public static void writeCSV(List<string> headList, List<string> valList, string fileName)
{
string headerString = "";
string value = "";
if (!File.Exists(fileName))
{
foreach (var header in headList)
{
foreach (var val in valList)
{
value += val + ",";
}
oldHeadList.Add(header);
headerString += header + ',';
}
headerString += "+" + Environment.NewLine;
File.WriteAllText(fileName, headerString);
}
else
{
foreach (var header in headList)
{
foreach (var oldHeader in oldHeadList)
{
foreach (var val in valList)
{
if (header != oldHeader)
{
value += "null,";
}
else
{
value += val + ",";
}
}
}
}
}
File.AppendAllText(fileName, value);
value += Environment.NewLine;
}
}
My horrific json file that I cannot change as its used by my company: https://codeshare.io/rGL6K5
Is there some kind of pattern?
Reason I am asking is, maybe you could create a service that serialize the JSON to a complex object(s). Once that is done have a service that serializes that object to csv. The service would know to write multiple csv files as needed.
I'd stay away from using {dynamic}, if there is a reliable pattern to the JSON. I'd get a sample JSON file, copy it into the clipboard and using the Paste JSON to Classes feature in Visual Studio.
https://blogs.msdn.microsoft.com/webdev/2012/12/18/paste-json-as-classes-in-asp-net-and-web-tools-2012-2-rc/
After that, deserialize it with Newtonsoft.JSON into a nice reliable object from which to build your CSV.

Deserialize json string to object in c# in Key value pair (Comma separated values)

I have below json in string as parameter to a WebMethod.
How can I deserialize in such a way that value comes in Key value pair.
Json String Parameter:
["Ref No,0","Date,0","Amt,0","Sender Name,0","Sender Add,0","Beneficiary Name,0","Beneficiary Add,0","Phone,0","Secret Code,0","Secret Ans,0","Preferred Id,0"]
WebMethod:
[System.Web.Services.WebMethod]
public static string SaveMappings(string mappingData)
{
//string str = "{\"Arg1\":\"Arg1Value\",\"Arg2\":\"Arg2Value\"}";
//JavaScriptSerializer serializer = new JavaScriptSerializer();
//object obj;
//var data = serializer.Deserialize(mappingData,);
var data = mappingData.ToArray();
if (data != null)
{
}
var d2 = mappingData.Split(',');
if (d2!=null)
{
}
return mappingData;
}
If you need to work with JSON data then use Newtonsoft.JSON library.
Convert the object to an array of strings and then split every line.
With this approach you can be sure that the given string is actually an JSON array and it is correct.
var str = "[\"Ref No,0\",\"Date,0\",\"Amt,0\",\"Sender Name,0\",\"Sender Add,0\",\"Beneficiary Name,0\",\"Beneficiary Add,0\",\"Phone,0\",\"Secret Code,0\",\"Secret Ans,0\",\"Preferred Id,0\"]";
string[] objs = JsonConvert.DeserializeObject<string[]>(str);
Dictionary<string, string> dic = new Dictionary<string, string>();
foreach (var obj in objs)
{
var keyValue = obj.Split(',');
dic.Add(keyValue[0], keyValue[1]);
}
foreach (var record in dic)
{
Console.WriteLine("{0} => {1}", record.Key, record.Value);
}
Or this one using LINQ. It looks better and it can be written faster. However, it is less optimal (two calls of Split instead of one).
public Dictionary<string, string> FromJsonArray(string jsonArray)
{
return JsonConvert.DeserializeObject<string[]>(jsonArray)
.ToDictionary(obj => obj.Split(',')[0], obj => obj.Split(',')[1]);
}
// ...
var str = "[\"Ref No,0\",\"Date,0\",\"Amt,0\",\"Sender Name,0\",\"Sender Add,0\",\"Beneficiary Name,0\",\"Beneficiary Add,0\",\"Phone,0\",\"Secret Code,0\",\"Secret Ans,0\",\"Preferred Id,0\"]";
foreach (var record in FromJsonArray(str))
{
Console.WriteLine("{0} => {1}", record.Key, record.Value);
}
why don't you just change every ',' in the string array to ':' then pass it to the method, from what you wrote in the question, this should work

deserialize index based json object - c#

I am using Newtonsoft and Newtonsoft.Json. I have the below json:
string strJson_StorageInfo = "[{10:\"test\"}, {20:\"test1\"}]";
List<Dictionary<int, string>> jobj = (List<Dictionary<int, string>>) JsonConvert.DeserializeObject(strJson_StorageInfo, typeof(List<Dictionary<int, string>>));
foreach (Dictionary<int, string> dicStorageInfo in jobj) {
foreach (KeyValuePair<int, string> StorageItem in dicStorageInfo) {
Response.Write("key : " + StorageItem.Key + " , value : " + StorageItem.Value + "</br>");
}
}
I need to Deserialize this. Can anyone suggest me good method. Thanks in advance
you can use below mentioned code
string strJson_StorageInfo = "[{10:\"test\"}, {20:\"test1\"}]";
var abc = JsonConvert.DeserializeObject <List<Dictionary<int, string>>>(strJson_StorageInfo);
after you can find the keys and Values from it
var K = abc.Select(p => p.Keys);
var V = abc.Select(p => p.Values);
ok. I compromised with Json Format String. I have changed the json string. Found similar thread in How can I deserialize JSON to a simple Dictionary<string,string> in ASP.NET?. Thanks.
This worked for me.. I am not sure if it works in asp.net 2.0
string strJson_StorageInfo = "[{10:\"test\"}, {20:\"test1\"}]";
List<Dictionary<int, string>> values = JsonConvert.DeserializeObject<List<Dictionary<int, string>>>(strJson_StorageInfo);
foreach (var items in values)
{
foreach (var item in items)
{
Label1.Text += "Key: " + item.Key.ToString() + " Value: " + item.Value.ToString() + "<br/>";
}
}

How to convert json to NameValueCollection

How could you convert a string of JSON to a C# NameValueCollection simply, preferably without using a 3rd party parser?
I'm not sure why everyone is still recommending JSON.NET for deserialization of JSON. I wrote a blog post on how to deserialize JSON to C#.
In short, it's like this:
using System.Web.Script.Serialization;
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string, string>>(jsonText);
NameValueCollection nvc = null;
if (dict != null) {
nvc = new NameValueCollection(dict.Count);
foreach (var k in dict) {
nvc.Add(k.Key, k.Value);
}
}
}
var json = jss.Serialize(dict);
Console.WriteLine(json);
Be sure to add a reference to System.Web.Extensions.dll.
Note:
I usually deserialize to dynamic, so I'm assuming that NameValueCollection would work. However, I haven't verified if it actually does.
EDIT
Pure .net solution without third party development have look : JavaScriptSerializer – Dictionary to JSON Serialization and Deserialization
make use of Json.NET
string jsonstring = #"{""keyabc"":""valueabc"",""keyxyz"":""valuexyz""}";
Dictionary<string, string> values =
JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonstring);
Check #jon answer suggest same : .Net Linq to JSON with Newtonsoft JSON library
If your JSON contains nested objects whithin it the solution below will handle them properly (based on JSON.NET, but you can adapt to the JSON parser of your choice).
This usage example:
var json = "{\"status\":\"paid\",\"date\":\"2019-10-09T17:30:51.479Z\",\"customer\":{\"id\":123456789,\"country\":\"br\",\"name\":\"Thomas Vilhena\",\"phone_numbers\":[\"+5511987654321\"],\"documents\":[{\"id\":\"doc_id\"}]}}";
var dict = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);
var nvc = new NameValueCollection(dict.Count);
AddKeyValuePairs(nvc, dict);
Console.WriteLine(nvc["status"]);
Console.WriteLine(nvc["date"]);
Console.WriteLine(nvc["customer[phone_numbers][0]"]);
Console.WriteLine(nvc["customer[id]"]);
Console.WriteLine(nvc["customer[documents][0][id]"]);
Produces the following output:
paid
09.10.2019 17:30
+5511987654321
123456789
doc_id
And here's the implementation:
private static void AddKeyValuePairs(
NameValueCollection nvc,
Dictionary<string, object> dict,
string prefix = null)
{
foreach (var k in dict)
{
var key = prefix == null ? k.Key : prefix + "[" + k.Key + "]";
if (k.Value != null)
AddKeyValuePair(nvc, key, k.Value);
}
}
private static void AddKeyValuePair(
NameValueCollection nvc,
string key,
object value)
{
if (value is string || value.GetType().IsPrimitive)
{
nvc.Add(key, value.ToString());
}
else if (value is DateTime)
{
nvc.Add(key, ((DateTime)value).ToString("g"));
}
else
{
AddNonPrimitiveValue(nvc, key, value);
}
}
private static void AddNonPrimitiveValue(
NameValueCollection nvc,
string key,
object value)
{
var a = value as JArray;
if (a != null)
{
for (int i = 0; i < a.Count; i++)
AddKeyValuePair(nvc, key + "[" + i + "]", a[i]);
}
else
{
var v = value as JValue;
if (v != null)
{
AddKeyValuePair(nvc, key, v.Value);
}
else
{
var j = value as JObject;
if (j != null)
AddKeyValuePairs(nvc, j.ToObject<Dictionary<string, object>>(), key);
}
}
}

Categories

Resources