I am trying to pass a json string to a C#-Program using Commandline.
The JSON-String looks like this:
{
"config": {
"script": {
"script_name": "test",
"dir": "D:\\test",
"destination": "M:\\neu\\test",
"params": "/b /s /r:3 /w:5"
}
}
}
In Commandline it looks like this:
{"config":{"script":{"script_name":"test","dir":"D:\\test","destination":"M:\\neu\\test","params":"/b /s /r:3 /w:5"}}}
But if I just pass the string then it gets chunked into several pieces. But I want my program to see it as just a single string.
Do I have to adapt my JSON-String?
Declare it as a string with "" and escape the other " with \ and it should work.
Command line:
"{\"config\":{\"script\":{\"script_name\":\"test\",\"dir\":\"D:\\test\",\"destination\":\"M:\\neu\\test\",\"params\":\"/b /s /r:3 /w:5\"}}}"
This should work:
var jsonString = Environment.CommandLine;
I tested it with the debugger like so:
var jsonString = Environment.CommandLine;
// (*) This correction makes it work, although it is pretty ugly:
jsonString = jsonString.Split(new string[] { ".exe\" " }, StringSplitOptions.None)[1];
var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(jsonString);
Debugging with VS2015, and not modifying the json input (not even removing the line changes). I am using the same structure as your input:
public class Script
{
public string script_name { get; set; }
public string dir { get; set; }
public string destination { get; set; }
public string #params { get; set; }
}
public class Config
{
public Script script { get; set; }
}
public class RootObject
{
public Config config { get; set; }
}
About (*) => The problem with the deserialization is that the exe info is added in front of the command line with Environment.CommandLine and it "pollutes" the json like this: jsonString =
"path\to\assembly\name.vshost.exe" {
"config": {
"script": {
"script_name": "test",
"dir": "D:\\test",
"destination": "M:\\neu\\test",
"params": "/b /s /r:3 /w:5"
}
}
}
If anybody has a prettier fix to this problem please let me know.
Try to save the JSON object into a file, and pass the file as the argument to your application.
#Wildcard27 :
This is an actual use case in order to create Windows Tasks which was used for the faculty degree app. The JSON was just a simple serialization of a DTO that I was using.
When you serialize the JSON, just save it into a blank file, giving it a proper name so that is unique.
private string CreateTaskConfigurationFile(string taskName, EquipmentEventExtended eventData, string host)
{
List<Change> changes = new List<Change>
{
new Change(MailConstants.EventName,eventData.EventName),
new Change(MailConstants.Deadline, eventData.DateTo.Value.ToShortDateString()),
new Change(MailConstants.EventDetails, eventData.EventDetails),
new Change(MailConstants.Link,$"{host}/Inventory/Details/{eventData.InventoryId}")
};
MailTaskModel mtm = new MailTaskModel
{
Body = MailConstants.UpdateTemplate(MailConstants.TaskMailTemplate, changes),
Subject = "[Reminder] Upcoming Event needs your attention",
ToAddress = "abcdef#gmail.com",
IsHtml = true
};
var fileName = string.Format(#"E:\{0}.json", taskName);
using (StreamWriter file = File.CreateText(fileName))
{
JsonSerializer js = new JsonSerializer();
js.Serialize(file, mtm);
}
return fileName;
}
Then you provide the file path as an argument to the console application:
static void Main(string[] args)
{
var configFilePath = args[0];
var mailConfig = LoadConfigurationFile(configFilePath);
MailManager manager = new MailManager(mailConfig.ToAddress, mailConfig.FromAddress,mailConfig.Subject, mailConfig.Body,mailConfig.IsHtml);
manager.SendMail();
}
private static MailTaskModel LoadConfigurationFile(string configurationFilePath)
{
MailTaskModel mailConfig;
using(var sr = new StreamReader(configurationFilePath))
{
string json = sr.ReadToEnd();
mailConfig = JsonConvert.DeserializeObject<MailTaskModel>(json);
}
return mailConfig;
}
You can then use something like
ConsoleApplication.exe -yourFilePath
I've removed noisy check-ups for nulls and all that so that it's more clear.
Instead of looking at the "string[] args" you could use Environment.CommandLine.
From MSDN https://msdn.microsoft.com/en-us/library/system.environment.commandline.aspx
public static void Main()
{
Console.WriteLine();
// Invoke this sample with an arbitrary set of command line arguments.
Console.WriteLine("CommandLine: {0}", Environment.CommandLine);
}
// The example displays output like the following:
// C:>env0 ARBITRARY TEXT
//
// CommandLine: env0 ARBITRARY TEXT
Just send json value to commandline after catch value and replace it. It's work for me.
args[1].Replace("{","{\"").Replace(":","\":\"").Replace(",","\",\"").Replace("}","\"}");
Following on from #Selcuk Gurals post, here is a more complete answer:
args[1].Replace("{", "{\"").Replace(":", "\":\"").Replace(",", "\",\"").Replace("}", "\"}").Replace(":\"[", ":[").Replace(":\"{", ":{").Replace("https\":\"", "https:").Replace("http\":\"", "http:").Replace("\":\"9", ":9").Replace("}\",", "},").Replace("]\",", "],").Replace("}\"}", "}}");
This caters for things like embedded http/https and ports. My port number was in the 9000 region... So a regex solution would be better. But it improves on the former answer
The value part of a JSON key/value pair can also be:
another JSON object
a list
"key": {}, ....
"key":[], ....
Related
I have a Json file, it contains connectionstring. I want to asynchronously read the file and deserialize it to a ConnectionString object and I always get a null result. I'm using .NET Core 6 and System.Text.Json.
Here is contents of my Json file:
{
"ConnectionStrings": {
"ConnStr": "Data Source=(local);Initial Catalog=MyData;Integrated Security=False;TrustServerCertificate=True;Persist Security Info=False;Async=True;MultipleActiveResultSets=true;User ID=sa;Password=MySecret;",
"ProviderName": "SQLServer"
}
}
Here are the contents of my classes:
internal class DBConnectionString
{
[JsonPropertyName("ConnStr")]
public string ConnStr { get; set; }
[JsonPropertyName("ProviderName")]
public string ProviderName { get; set; }
public DBConnectionString()
{
}
}
public class DBConnStr {
private static string AppSettingFilePath => "appsettings.json";
public static async Task<string> GetConnectionStringAsync()
{
string connStr = "";
if (File.Exists((DBConnStr.AppSettingFilePath)))
{
using (FileStream sr = new FileStream(AppSettingFilePath, FileMode.Open, FileAccess.Read))
{
//string json = await sr.ReadToEndAsync();
System.Text.Json.JsonDocumentOptions docOpt = new System.Text.Json.JsonDocumentOptions() { AllowTrailingCommas = true };
using (var document = await System.Text.Json.JsonDocument.ParseAsync(sr, docOpt))
{
System.Text.Json.JsonSerializerOptions opt = new System.Text.Json.JsonSerializerOptions() { AllowTrailingCommas = true, PropertyNameCaseInsensitive = true };
System.Text.Json.JsonElement root = document.RootElement;
System.Text.Json.JsonElement element = root.GetProperty("ConnectionStrings");
sr.Position = 0;
var dbConStr = await System.Text.Json.JsonSerializer.DeserializeAsync<DBConnectionString>(sr, opt);
if (dbConStr != null)
{
connStr = dbConStr.ConnStr;
}
}
}
}
return connStr;
}
}
The following is the syntax that I use to call the GetConnectionStringAsync method:
string ConnectionString = DBConnStr.GetConnectionStringAsync().Result;
When the application is running in debug mode, I checked, on line
var dbConStr = await
System.Text.Json.JsonSerializer.DeserializeAsync(sr,
opt);
The DBConnectionString object property is always empty.
I also tried the reference on the Microsoft website, https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/how-to?pivots=dotnet-6-0 but it doesn't work succeed.
using System.Text.Json;
namespace DeserializeFromFileAsync
{
public class WeatherForecast
{
public DateTimeOffset Date { get; set; }
public int TemperatureCelsius { get; set; }
public string? Summary { get; set; }
}
public class Program
{
public static async Task Main()
{
string fileName = "WeatherForecast.json";
using FileStream openStream = File.OpenRead(fileName);
WeatherForecast? weatherForecast =
await JsonSerializer.DeserializeAsync<WeatherForecast>(openStream);
Console.WriteLine($"Date: {weatherForecast?.Date}");
Console.WriteLine($"TemperatureCelsius: {weatherForecast?.TemperatureCelsius}");
Console.WriteLine($"Summary: {weatherForecast?.Summary}");
}
}
}
Do you have a solution for my problem or a better solution? I appreciate all your help. Thanks
Sorry about my English if it's not good, because I'm not fluent in English and use google translate to translate it
To begin with, if you want to read information from appSettings.json, you should explore more into reading configurations. There are helper classes provided by .Net for the same.
Coming back to your code, if you want to use your own code for Json Deserialization, then you need to make the following change to it.
var dbConStr = System.Text.Json.JsonSerializer.Deserialize<DBConnectionString>(element.GetRawText(), opt);
where, element according to code shared in the question is defined as
System.Text.Json.JsonElement element = root.GetProperty("ConnectionStrings");
This ensures the Raw Json associated with the JsonElement ConnectStrings is de-serialized.
However, I recommend you to read more into Reading configurations using the IConfiguration and related .Net helpers.
I'm currently setting-up my application, and i need to manage a json file (that contain some settings) in my windows form. Once you open it, you can easy choose different settings, and once you've done, you can save it (which mean i need to overwrite the existing one json file settings, and replace it with new one!
I tried to follow this guide for correctly create my json file! But i met 2 problems:
This solution mentioned up, create square brackets (which i don't need!)
Seems to create all settings on one line. Is that correct or it could make some problem in the future?
Some materials....
My application:
Original json file:
Json file generated with my code:
My class:
public class data
{
public bool avx { get; set; }
public bool memory_pool { get; set; }
public bool smt { get; set; }
public bool spectre { get; set; }
public bool unlock_menu { get; set; }
public bool vinput { get; set; }
public double cpu_memory_pool_fraction { get; set; }
public double gpu_memory_pool_fraction { get; set; }
}
My code:
private void btn_save_Click(object sender, EventArgs e)
{
string settings_path = general_path + "\\plugins\\cyber_engine_tweaks\\" + "config.json"; //path
bool avx_set = cb_avx.Checked;
bool smt_set = cb_smt.Checked;
bool memory_set = cb_memory.Checked;
bool spectre_set = cb_spectre.Checked;
bool debug_set = cb_debug.Checked;
bool vinput_set = cb_vinput.Checked;
List<data> _data = new List<data>();
_data.Add(new data()
{
avx = avx_set,
cpu_memory_pool_fraction = 0.5,
gpu_memory_pool_fraction = 1.0,
memory_pool = memory_set,
smt = smt_set,
spectre = spectre_set,
unlock_menu = debug_set,
vinput = vinput_set
});
using (StreamWriter file = File.CreateText(settings_path))
{
JsonSerializer serializer = new JsonSerializer();
//serialize object directly into file stream
serializer.Serialize(file, _data);
}
}
Square brackets are because you send an array:
Instead of
List<data> _data = new List<data>(); _data.Add(new data()...
try
var data = new data()... serializer.Serialize(file, data)
All settings on one line is normal.
Very nice detailed answer here: Can JSON start with "["?
TLDR:
It's not a Json without either {} indicating an object or [] indicating an array. So no, you can't have a json with multiple keys without one.
The newlines are optional in Json. Since most json objects are used for transfering over the wire, there is no need for newlines (which take up unessecary bytes).
Issues:
1 . This solution mentioned up, create square brackets (which i don't need!)
Solution:
Create your data object like:
//List<data> _data = new List<data>();
data _data = new data
{
avx = avx_set,
cpu_memory_pool_fraction = 0.5,
gpu_memory_pool_fraction = 1.0,
memory_pool = memory_set,
smt = smt_set,
spectre = spectre_set,
unlock_menu = debug_set,
vinput = vinput_set
};
2 . Seems to create all settings on one line. Is that correct or it could make some problem in the future?
Solution:
I think it's a format issue. Can igonore
I have several text files with the following data structure:
{
huge
json
block that spans across multiple lines
}
--#newjson#--
{
huge
json
block that spans across multiple lines
}
--#newjson#--
{
huge
json
block that spans across multiple lines
} etc....
So it is actually json blocks that are row delimited by "--##newjson##--" string .
I am trying to write a customer extractor to parse this. The problem is that I can't use string data type to feed json deserializer because it has a maximum size of 128 KB and the json blocks do not fit in this. What is the best approach to parse this file using a custom extractor?
I have tried using the code below, but it doesn't work. Even the row delimiter "--#newjson#--" doesn't seem to work right.
public SampleExtractor(Encoding encoding, string row_delim = "--#newjson#--", char col_delim = ';')
{
this._encoding = ((encoding == null) ? Encoding.UTF8 : encoding);
this._row_delim = this._encoding.GetBytes(row_delim);
this._col_delim = col_delim;
}
public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output)
{
//Read the input by json
foreach (Stream current in input.Split(_encoding.GetBytes("--#newjson#--")))
{
var serializer = new JsonSerializer();
using (var sr = new StreamReader(current))
using (var jsonTextReader = new JsonTextReader(sr))
{
var jsonrow = serializer.Deserialize<JsonRow>(jsonTextReader);
output.Set(0, jsonrow.status.timestamp);
}
yield return output.AsReadOnly();
}
}
You dont need a custom extractor to do that.
The best solution is add one json by line. Then you can use a text extractor and extract line by line. You can also pick your own delimiter.
REFERENCE ASSEMBLY [Newtonsoft.Json];
REFERENCE ASSEMBLY [Microsoft.Analytics.Samples.Formats];
#JsonLines=
EXTRACT
[JsonLine] string
FROM
#Full_Path
USING
Extractors.Text(delimiter:'\b', quoting : false);
#ParsedJSONLines =
SELECT
Microsoft.Analytics.Samples.Formats.Json.JsonFunctions.JsonTuple([JsonLine]) AS JSONLine
FROM
#JsonLines
#AccessToProperties=
SELECT
JSONLine["Property"] AS Property
FROM
#ParsedJSONLines;
Here is how you can achieve the solution:
1) Create a c# equivalent of your JSON object
Note:- Assuming all your json object are same in your text file.
E.g:
Json Code
{
"id": 1,
"value": "hello",
"another_value": "world",
"value_obj": {
"name": "obj1"
},
"value_list": [
1,
2,
3
]
}
C# Equivalent
public class ValueObj
{
public string name { get; set; }
}
public class RootObject
{
public int id { get; set; }
public string value { get; set; }
public string another_value { get; set; }
public ValueObj value_obj { get; set; }
public List<int> value_list { get; set; }
}
2) Change your de-serializing code like below after you have done the split based on the delimiter
using (JsonReader reader = new JsonTextReader(sr))
{
while (!sr.EndOfStream)
{
o = serializer.Deserialize<List<MyObject>>(reader);
}
}
This would deserialize the json data in c# class object which would solve your purpose.
Later which you can serialize again or print it in text or ...any file.
Hope it helps.
Given below is the type of JSON response ,
{
"?xml":{
"#version":"1.0",
"#encoding":"iso-8859-1"
},
"xmlreport":{
"#title":"ABC: TEST Most Saved2",
"#dates":"Week of May 19,2013",
"columns":{
"column":[
{
"#name":"Page",
"#type":"dimension",
"#text":"Page"
},
{
"#name":"Events",
"#type":"metric",
"#hastotals":"true",
"#text":"Events"
}
]
},
"rows":{
"row":[
{
"#rownum":"1",
"cell":[
{
"#columnname":"page",
"#csv":"\"http://www.ABC.com/profile/recipebox\"",
"#text":"http://www.ABC.com/profile/recipebox"
},
{
"#columnname":"events",
"#percentage":"\"0.1%\"",
"#text":"489"
}
]
},
{
"#rownum":"2",
"cell":[
{
"#columnname":"page",
"#csv":"\"http://www.ABC.com/recipes/peanut-butter-truffle-brownies/c5c602e4-007b-43e0-aaab-2f9aed89524c\"",
"#text":"http://www.ABC.com/recip...c602e4-007b-43e0-aaab-2f9aed89524c"
},
{
"#columnname":"events",
"#percentage":"\"0.0%\"",
"#text":"380"
}
]
}
]
},
"totals":{
"pagetotals":{
"total":{
"#columnname":"events",
"#value":"1820.000000",
"#text":"1,820 (0.2%)"
}
},
"reporttotals":{
"total":{
"#columnname":"events",
"#value":"7838.000000",
"#text":"7,838 (0.8%)"
}
},
"timeperiodtotals":{
"total":{
"#columnname":"events",
"#value":"955774.000000",
"#text":"955,774 (100.0%)"
}
}
}
}
}
I am unable to parse the object.Could you please help me out how do I read the attributes and elements after parsing. I am using C#
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(XML);
string jsonText = JsonConvert.SerializeXmlNode(doc);
//var result = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonText, "xmlreport");
var results = JsonConvert.DeserializeObject<dynamic>(jsonText);
JToken token = JObject.Parse(jsonText);
var report = token["xmlreport"];
}
My understanding of the question is you've got some Xml and you need to send out json. Couple of points before we get to the code:
1) Don't convert xml to json directly as it causes issues
2) Parse the xml to objects at your end and then work out the format to return; decoupling what comes in and goes out will allow for one of the interfaces to change in the future without impacting the other as you can tweak the mapping
So, onto the code ...
Essentially parse the xml to objects to allow for further processing and then push out as json.
class Program
{
private static string starting =
"<xmlreport title=\"ABC: TEST Most Saved2\" dates=\"Week of May 19,2013\"><columns><column name=\"Page\" type=\"dimension\">Page</column><column name=\"Events\" type=\"metric\" hastotals=\"true\">Events</column></columns><rows><row rownum=\"1\"><cell columnname=\"page\" csv=\"http://www.ABC.com/profile/recipebox\">http://www.ABC.com/profile/recipebox</cell><cell columnname=\"events\" percentage=\"0.1%\">489</cell></row><row rownum=\"2\"><cell columnname=\"page\" csv=\"http://www.ABC.com/recipes/peanut-butter-truffle-brownies/c5c602e4-007b-43e0-aaab-2f9aed89524c\">http://www.ABC.com/recipes/peanut-butter-truffle-brownies/c5c602e4-007b-43e0-aaab-2f9aed89524c</cell><cell columnname=\"events\" percentage=\"0.0%\">380</cell></row></rows><totals><pagetotals><total columnname=\"events\" value=\"1820.00000\">1,820 (0.2%)</total></pagetotals><reporttotals><total columnname=\"events\" value=\"7838.000000\">7,838 (0.8%)</total></reporttotals><timeperiodtotals><total columnname=\"events\" value=\"955774.000000\">955,774 (100.0%)</total></timeperiodtotals></totals></xmlreport>";
static void Main(string[] args)
{
// parse from xml to objects
StringReader reader = new StringReader(starting);
XmlSerializer xmlSerializer = new XmlSerializer(typeof(XmlReport));
var xmlreport = (XmlReport)xmlSerializer.Deserialize(reader);
// todo: do some process mapping ...
// parse out as json
var json = JsonConvert.SerializeObject(xmlreport);
Console.WriteLine(json);
Console.ReadLine();
}
}
[Serializable]
[XmlRoot(ElementName = "xmlreport")]
public class XmlReport
{
[XmlAttribute(AttributeName = "title")]
public string Title { get; set; }
[XmlAttribute(AttributeName = "dates")]
public string Dates { get; set; }
[XmlArray(ElementName = "columns")]
[XmlArrayItem(typeof(Column), ElementName = "column")]
public Collection<Column> Columns { get; set; }
}
[Serializable]
public class Column
{
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "type")]
public string Type { get; set; }
}
I've tried to parse the json to the original xml to begin with so appologies if I've not interpreted it properly. I've not done the entire structure but I hope the example above gives you an idea of how to do the rest.
Hope this helps.
One way of doing this is by getting the actual Data Structure of that JSON object that you have there.
Then create classes representing that data structure (if you can get a complete response -- having all properties, you just use this site to convert that to classes).
After that, deserialize that JSON object into your class using different libraries available. A sample could be this one.
Use this (JSon.NET) and a recursive function writes all keys and values to output window.
[TestMethod]
public void ParseMePlease()
{
string s = #"{""?xml"":{""#version"":""1.0"",""#encoding"":""iso-8859-1""},
""xmlreport"":{""#title"":""ABC: TEST Most Saved2"",""#dates"":""Week of May 19,2013"",
""columns"":{""column"":[{""#name"":""Page"",""#type"":""dimension"",""#text"":""Page""},{""#name"":""Events"",""#type"":""metric"",""#hastotals"":""true"",""#text"":""Events""}]},
""rows"":
{""row"":[{""#rownum"":""1"",""cell"":[{""#columnname"":""page"",""#csv"":""\""http://www.ABC.com/profile/recipebox\"""",""#text"":""http://www.ABC.com/profile/recipebox""},{""#columnname"":""events"",""#percentage"":""\""0.1%\"""",""#text"":""489""}]},
{""#rownum"":""2"",""cell"":[{""#columnname"":""page"",""#csv"":""\""http://www.ABC.com/recipes/peanut-butter-truffle-brownies/c5c602e4-007b-43e0-aaab-2f9aed89524c\"""",""#text"":""http://www.ABC.com/recip...c602e4-007b-43e0-aaab-2f9aed89524c""},{""#columnname"":""events"",""#percentage"":""\""0.0%\"""",""#text"":""380""}]}]},
""totals"":{""pagetotals"":{""total"":{""#columnname"":""events"",""#value"":""1820.000000"",""#text"":""1,820 (0.2%)""}},
""reporttotals"":{""total"":{""#columnname"":""events"",""#value"":""7838.000000"",""#text"":""7,838 (0.8%)""}},
""timeperiodtotals"":{""total"":{""#columnname"":""events"",""#value"":""955774.000000"",""#text"":""955,774 (100.0%)""}}}}}";
var result=JsonConvert.DeserializeObject<object>(s);
Debug.WriteLine("Right Click Result on quick watch for Result Views!(On Debug)"+result.ToString() );
JObject jobject = ((Newtonsoft.Json.Linq.JObject)result);
PrintDetail(jobject);
}
public void PrintDetail(JObject node)
{
foreach (var item in node)
{
Debug.WriteLine("Key:" + item.Key + " Value:" + item.Value);
if (item.Value is JObject)
{
PrintDetail((JObject)item.Value);
}
}
}
How does one read a very large JSON file into an array in c# to be split up for later processing?
I have managed to get something working that will:
Read the file Miss out headers and only read values into array.
Place a certain amount of values on each line of an array. (So I
could later split it an put into 2d array)
This was done with the code below but it crashes the program after entering a few lines into the array. This might have to do with the file size.
// If the file extension was a jave file the following
// load method will be use else it will move on to the
// next else if statement
if (fileExtension == ".json")
{
int count = 0;
int count2 = 0;
int inOrOut = 0;
int nRecords=1;
JsonTextReader reader = new JsonTextReader(new StreamReader(txtLoaction.Text));
string[] rawData = new string[5];
while (reader.Read())
{
if (reader.Value != null)
if (inOrOut == 1)
{
if (count == 6)
{
nRecords++;
Array.Resize(ref rawData, nRecords);
//textBox1.Text += "\r\n";
count = 0;
}
rawData[count2] += reader.Value + ","; //+"\r\n"
inOrOut = 0;
count++;
if (count2 == 500)
{
MessageBox.Show(rawData[499]);
}
}
else
{
inOrOut = 1;
}
}
}
A snippet of the JSON I am working with is:
[
{ "millis": "1000",
"stamp": "1273010254",
"datetime": "2010/5/4 21:57:34",
"light": "333",
"temp": "78.32",
"vcc": "3.54" },
]
I need the values out of this JSON. For example, I need "3.54", but I would not want it to print the "vcc".
How can one read a JSON file in and only extract the data needed to be put into an array?
How about making everything easier with Json.NET?
public void LoadJson()
{
using (StreamReader r = new StreamReader("file.json"))
{
string json = r.ReadToEnd();
List<Item> items = JsonConvert.DeserializeObject<List<Item>>(json);
}
}
public class Item
{
public int millis;
public string stamp;
public DateTime datetime;
public string light;
public float temp;
public float vcc;
}
You can even get the values dynamically without declaring Item class.
dynamic array = JsonConvert.DeserializeObject(json);
foreach(var item in array)
{
Console.WriteLine("{0} {1}", item.temp, item.vcc);
}
Doing this yourself is an awful idea. Use Json.NET. It has already solved the problem better than most programmers could if they were given months on end to work on it. As for your specific needs, parsing into arrays and such, check the documentation, particularly on JsonTextReader. Basically, Json.NET handles JSON arrays natively and will parse them into strings, ints, or whatever the type happens to be without prompting from you. Here is a direct link to the basic code usages for both the reader and the writer, so you can have that open in a spare window while you're learning to work with this.
This is for the best: Be lazy this time and use a library so you solve this common problem forever.
Answer for .NET Core
You can just use the built-in System.Text.Json instead of the 3rd-party Json.NET. To promote reuse, the JSON-file-reading functionality belongs in its own class and should be generic rather than hard-coded to a certain type (Item). Here's a full example:
using System;
using System.IO;
using System.Text.Json;
using System.Threading.Tasks;
namespace Project
{
class Program
{
static async Task Main()
{
Item item = await JsonFileReader.ReadAsync<Item>(#"C:\myFile.json");
}
}
public static class JsonFileReader
{
public static async Task<T> ReadAsync<T>(string filePath)
{
using FileStream stream = File.OpenRead(filePath);
return await JsonSerializer.DeserializeAsync<T>(stream);
}
}
public class Item
{
public int millis;
public string stamp;
public DateTime datetime;
public string light;
public float temp;
public float vcc;
}
}
Or, if you prefer something simpler/synchronous:
class Program
{
static void Main()
{
Item item = JsonFileReader.Read<Item>(#"C:\myFile.json");
}
}
public static class JsonFileReader
{
public static T Read<T>(string filePath)
{
string text = File.ReadAllText(filePath);
return JsonSerializer.Deserialize<T>(text);
}
}
This can also be done in the following way:
JObject data = JObject.Parse(File.ReadAllText(MyFilePath));
string jsonFilePath = #"C:\MyFolder\myFile.json";
string json = File.ReadAllText(jsonFilePath);
Dictionary<string, object> json_Dictionary = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(json);
foreach (var item in json_Dictionary)
{
// parse here
}
Based on #L.B.'s solution, the (typed as Object rather than Anonymous) VB code is
Dim oJson As Object = JsonConvert.DeserializeObject(File.ReadAllText(MyFilePath))
I should mention that this is quick and useful for constructing HTTP call content where the type isn't required. And using Object rather than Anonymous means you can maintain Option Strict On in your Visual Studio environment - I hate turning that off.
For any of the JSON parse, use the website http://json2csharp.com/ (easiest way) to convert your JSON into C# class to deserialize your JSON into C# object.
public class JSONClass
{
public string name { get; set; }
public string url { get; set; }
public bool visibility { get; set; }
public string idField { get; set; }
public bool defaultEvents { get; set; }
public string type { get; set; }
}
Then use the JavaScriptSerializer (from System.Web.Script.Serialization), in case you don't want any third party DLL like newtonsoft.
using (StreamReader r = new StreamReader("jsonfile.json"))
{
string json = r.ReadToEnd();
JavaScriptSerializer jss = new JavaScriptSerializer();
var Items = jss.Deserialize<JSONClass>(json);
}
Then you can get your object with Items.name or Items.Url etc.
Very Easiest way I found on online to work with .JSON file in C#(or any other Programming Language)
Prerequisite:-
Install Newtonsoft.Json Library into your Project
Newtonsoft.Json
and here is the URL -> https://app.quicktype.io/
Steps
1> go to this URL - https://app.quicktype.io/
2> Copy and Paste your JSON file structure into Left sidebar
app.quicktype.io
3> Select required Language (here C#) from Options menu
4> Copy generated code and go to your Project and Create a new .cs file with the same name(here "Welcome.cs")
Welcome.cs
5> Paste all generated code into the newly created class.
Welcome.cs pasted Code
6> that's it. :)
Steps to Access value
1> Go to Main Program .cs file or wherever you need to access it.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Access Json values using Keys.>");
String jsonString = new StreamReader("give <.json> file Path here").ReadToEnd();
// use below syntax to access JSON file
var jsonFile = Welcome.FromJson(jsonString);
string FileName = jsonFile.File;
long Lvl = jsonFile.Level;
bool isTrue = jsonFile.CSharp;
Console.WriteLine(FileName);//JSON
Console.WriteLine(Lvl);//1
Console.WriteLine(isTrue);//true
}
}
For finding the right path I'm using
var pathToJson = Path.Combine("my","path","config","default.Business.Area.json");
var r = new StreamReader(pathToJson);
var myJson = r.ReadToEnd();
// my/path/config/default.Business.Area.json
[...] do parsing here
Path.Combine uses the Path.PathSeparator and it checks whether the first path has already a separator at the end so it will not duplicate the separators. Additionally, it checks whether the path elements to combine have invalid chars.
See https://stackoverflow.com/a/32071002/4420355
There is a faster way of parsing json then Json.Net . If you are using .net core 3.0 or up then you can use the System.Text.Json nuget package to serialize or deserialize.
you need to add:
using System.Text.Json
And then you can serialize as:
var jsonStr = JsonSerializer.Serialize(model);
And Deserialize as:
var model = JsonSerializer.Deserialize(jsonStr);
This code can help you:
string _filePath = Path.GetDirectoryName(System.AppDomain.CurrentDomain.BaseDirectory);
JObject data = JObject.Parse(_filePath );
There is an easier way to get JSON from file or from the Web:
Json.Net.Curl
Install-Package Json.Net.Curl
// get JObject from local file system
var json = Json.Net.Curl.Get(#"data\JObjectUnitTest1.json");
var json = await Json.Net.Curl.GetAsync(#"data\JObjectUnitTest1.json")
// get JObject from Server
var json = await Json.Net.Curl.GetAsync("http://myserver.com/data.json");
GitHub Project
Nuget
With Cinchoo ETL, an open source library, parsing of very large JSON file is iterative and simple to use
1. Dynamic Method: - No POCO class required
string json = #"
[
{
""millis"": ""1000"",
""stamp"": ""1273010254"",
""datetime"": ""2010/5/4 21:57:34"",
""light"": ""333"",
""temp"": ""78.32"",
""vcc"": ""3.54""
},
{
""millis"": ""2000"",
""stamp"": ""1273010254"",
""datetime"": ""2010/5/4 21:57:34"",
""light"": ""333"",
""temp"": ""78.32"",
""vcc"": ""3.54""
}
]
";
using (var r = ChoJSONReader.LoadText(json))
{
foreach (var rec in r)
Console.WriteLine(rec.Dump());
}
Sample fiddle: https://dotnetfiddle.net/mo1qvw
2. POCO Method:
Define POCO class matching json attributes
public class Item
{
public int Millis { get; set; }
public string Stamp { get; set; }
public DateTime Datetime { get; set; }
public string Light { get; set; }
public float Temp { get; set; }
public float Vcc { get; set; }
}
Then using the parser to load the JSON as below
string json = #"
[
{
""millis"": ""1000"",
""stamp"": ""1273010254"",
""datetime"": ""2010/5/4 21:57:34"",
""light"": ""333"",
""temp"": ""78.32"",
""vcc"": ""3.54""
},
{
""millis"": ""2000"",
""stamp"": ""1273010254"",
""datetime"": ""2010/5/4 21:57:34"",
""light"": ""333"",
""temp"": ""78.32"",
""vcc"": ""3.54""
}
]
";
using (var r = ChoJSONReader<Item>.LoadText(json))
{
foreach (var rec in r)
Console.WriteLine(ChoUtility.Dump(rec));
}
Sample fiddle: https://dotnetfiddle.net/fRWu0w
Disclaimer: I'm author of this library.