I have a settings.json file present in the Release folder of my application. What I want to do is change the value of it, not temporarily, permanently.. That means, deleting the old entry, writing a new one and saving it.
Here is the format of the JSON file
{
"Admins":["234567"],
"ApiKey":"Text",
"mainLog": "syslog.log",
"UseSeparateProcesses": "false",
"AutoStartAllBots": "true",
"Bots": [
{
"Username":"BOT USERNAME",
"Password":"BOT PASSWORD",
"DisplayName":"TestBot",
"Backpack":"",
"ChatResponse":"Hi there bro",
"logFile": "TestBot.log",
"BotControlClass": "Text",
"MaximumTradeTime":180,
"MaximumActionGap":30,
"DisplayNamePrefix":"[AutomatedBot] ",
"TradePollingInterval":800,
"LogLevel":"Success",
"AutoStart": "true"
}
]
}
Suppose I want to change the password value and instead of BOT PASSWORD I want it to be only password. How do I do that?
Here's a simple & cheap way to do it (assuming .NET 4.0 and up):
string json = File.ReadAllText("settings.json");
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
jsonObj["Bots"][0]["Password"] = "new password";
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText("settings.json", output);
The use of dynamic lets you index right into json objects and arrays very simply. However, you do lose out on compile-time checking. For quick-and-dirty it's really nice but for production code you'd probably want the fully fleshed-out classes as per #gitesh.tyagi's solution.
Use the JObject class in Newtonsoft.Json.Linq to modify JSON values without knowing the JSON structure ahead of time:
using Newtonsoft.Json.Linq;
string jsonString = File.ReadAllText("myfile.json");
// Convert the JSON string to a JObject:
JObject jObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString) as JObject;
// Select a nested property using a single string:
JToken jToken = jObject.SelectToken("Bots[0].Password");
// Update the value of the property:
jToken.Replace("myNewPassword123");
// Convert the JObject back to a string:
string updatedJsonString = jObject.ToString();
File.WriteAllText("myfile.json", updatedJsonString);
Example:
// This is the JSON string from the question
string jsonString = "{\"Admins\":[\"234567\"],\"ApiKey\":\"Text\",\"mainLog\":\"syslog.log\",\"UseSeparateProcesses\":\"false\",\"AutoStartAllBots\":\"true\",\"Bots\":[{\"Username\":\"BOT USERNAME\",\"Password\":\"BOT PASSWORD\",\"DisplayName\":\"TestBot\",\"Backpack\":\"\",\"ChatResponse\":\"Hi there bro\",\"logFile\":\"TestBot.log\",\"BotControlClass\":\"Text\",\"MaximumTradeTime\":180,\"MaximumActionGap\":30,\"DisplayNamePrefix\":\"[AutomatedBot] \",\"TradePollingInterval\":800,\"LogLevel\":\"Success\",\"AutoStart\":\"true\"}]}";
JObject jObject = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonString) as JObject;
// Update a string value:
JToken jToken = jObject.SelectToken("Bots[0].Password");
jToken.Replace("myNewPassword123");
// Update an integer value:
JToken jToken2 = jObject.SelectToken("Bots[0].TradePollingInterval");
jToken2.Replace(555);
// Update a boolean value:
JToken jToken3 = jObject.SelectToken("Bots[0].AutoStart");
jToken3.Replace(false);
// Get an indented/formatted string:
string updatedJsonString = jObject.ToString();
//Output:
//{
// "Admins": [
// "234567"
// ],
// "ApiKey": "Text",
// "mainLog": "syslog.log",
// "UseSeparateProcesses": "false",
// "AutoStartAllBots": "true",
// "Bots": [
// {
// "Username": "BOT USERNAME",
// "Password": "password",
// "DisplayName": "TestBot",
// "Backpack": "",
// "ChatResponse": "Hi there bro",
// "logFile": "TestBot.log",
// "BotControlClass": "Text",
// "MaximumTradeTime": 180,
// "MaximumActionGap": 30,
// "DisplayNamePrefix": "[AutomatedBot] ",
// "TradePollingInterval": 555,
// "LogLevel": "Success",
// "AutoStart": false
// }
// ]
//}
You must have classes to instantiate json values to :
public class Bot
{
public string Username { get; set; }
public string Password { get; set; }
public string DisplayName { get; set; }
public string Backpack { get; set; }
public string ChatResponse { get; set; }
public string logFile { get; set; }
public string BotControlClass { get; set; }
public int MaximumTradeTime { get; set; }
public int MaximumActionGap { get; set; }
public string DisplayNamePrefix { get; set; }
public int TradePollingInterval { get; set; }
public string LogLevel { get; set; }
public string AutoStart { get; set; }
}
public class RootObject
{
public List<string> Admins { get; set; }
public string ApiKey { get; set; }
public string mainLog { get; set; }
public string UseSeparateProcesses { get; set; }
public string AutoStartAllBots { get; set; }
public List<Bot> Bots { get; set; }
}
Answer to your Ques(Untested code) :
//Read file to string
string json = File.ReadAllText("PATH TO settings.json");
//Deserialize from file to object:
var rootObject = new RootObject();
JsonConvert.PopulateObject(json, rootObject);
//Change Value
rootObject.Bots[0].Password = "password";
// serialize JSON directly to a file again
using (StreamWriter file = File.CreateText(#"PATH TO settings.json"))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, rootObject);
}
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 have this JSON string but are not sure how I will parse out the values that are inside:
has
has2
I do succeed to parse out the "id" correctly but are not sure how to access:
CORS
CORS2
CORS3
CORS4
I get the error:
'Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.String[]' because the type requires a JSON array (e.g. [1,2,3])
I have pasted the JSON in the pastebin:
https://pastebin.com/iWgGV9VK
The code I have:
public void getInfo()
{
String JSONstring = "{ id: 'hello', name: 'Hello',has:{ CORS: false,CORS2: true},has2:{ CORS3: false,CORS4: true}}";
String id = ""; List<String> has = new List<String>(); List<String> has2 = new List<String>();
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
id = deserializedTicker.id;
has = deserializedTicker.has.ToList();
has2 = deserializedTicker.has.ToList();
}
public class JsonInfo
{
public String id { get; set; }
public String[] has { get; set; }
public String[] has2 { get; set; }
}
I am trying with the dynamic approach using an object but gets an error here also:
''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
//responseBody holds the JSON string
dynamic stuff = JsonConvert.DeserializeObject(responseBody);
foreach (var info in stuff)
{
dynamic id = info.Value.id; //''Newtonsoft.Json.Linq.JValue' does not contain a definition for 'id''
dynamic has = info.Value.has;
dynamic has2 = info.Value.has2;
if (has != null && has2 != null)
{
dynamic cors = has.CORS;
if(cors != null)
{
MessageBox.Show(cors.ToString());
}
}
}
First off, let's correct your JSON:
{
"id": "hello",
"name": "Hello",
"has": {
"CORS": false,
"CORS2": true
},
"has2": {
"CORS3": false,
"CORS4": true
}
}
Now, the problem you are experiencing is because you are attempting to deserialize the value in "has" and "has2" as arrays. In the JSON, they are not arrays; they are objects. As such, you need to define new classes with the same properties so the JSON can be properly deserialized:
public class JsonInfo
{
public string id { get; set; }
public string name { get; set; }
public JsonHasInfo has { get; set; }
public JsonHas2Info has2 { get; set; }
}
public class JsonHasInfo
{
public bool CORS { get; set; }
public bool CORS2 { get; set; }
}
public class JsonHas2Info
{
public bool CORS3 { get; set; }
public bool CORS4 { get; set; }
}
Now you should be able to deserialize the (correct) JSON properly:
String JSONstring = "{ \"id\": \"hello\", \"name\": \"Hello\", \"has\": { \"CORS\": false, \"CORS2\": true }, \"has2\": { \"CORS3\": false, \"CORS4\": true } }\";"
var deserializedTicker = JsonConvert.DeserializeObject<JsonInfo>(JSONstring);
You json was incorrect, the key has contains a dict no list.
You need change your deserialize to dictionary or change your json.
Here you can see an example:
https://json-schema.org/understanding-json-schema/reference/array.html#array
In your JSON, has is an object, not an array. You should model your class to support an object containing the attributes CORS, CORS2, and so on, and so forth.
Edit: If you want to stick to has being an array, you should change your JSON to match what an array expects, which could be like: has: [ false, true ], and omit the CORS thing.
I am trying to deserialize JSON file and want to assign to object ScanResult. var text showing all the values but scanresult showing null some null values. https://gyazo.com/ff2ce386f845394c458a88d43a1f30d8
please suggest if I am missing something.
//MY jSon File SCAN Test 1-1543045410222.json 's code
{
"at": 1543045410222,
"i": 1000,
"s": {
"Sensor1": ["OFF"],
"Sensor2": ["OFF"],
"DataReady1": ["OFF"],
"DataReady2": ["OFF"],
"CV1": [5.0],
"CV2": [6.0]
}
}
//ViewModel Code is as below:
public void ResendScanResult()
{
var ScanActivities = scanActivityManager.GetAll();
foreach (var item in ScanActivities)
{
var scanName = item.ScanName;
var dir = _dataFilePath + scanName + "\\";
var jsonFileName = string.Format("{0}{1}-{2}.json", dir, scanName, item.ScanDateEpoch);
string fileName = Path.GetFileName(jsonFileName);
// ScanResult scanResult = new ScanResult();
var text = File.ReadAllText(jsonFileName);
//var scanResults = JsonConvert.DeserializeObject<ScanResult>(text);
Common.Model.ScanResult scanResult = JsonConvert.DeserializeObject<Common.Model.ScanResult>(text);
var Mvm = MonitorViewModel.Instance;
// TargetProvider target = Mvm.GetTargetProvider(scanResult);
// Mvm.PublishToServer(target, scanResult);
}
}
and my scanRescult class code is as below :
namespace ABX.Common.Model
{
public class ScanResult
{
public ScanResult()
{
At = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Interval = 1;
}
public string Name { get; set; }
public long At { get; set; }
public long Interval { get; set; }
public JObject Values { get; set; }
public string FileName { get; set; }
public JObject ToJson()
{
JObject json = new JObject
{
{ "at", At },
{ "i", Interval },
{ "s", Values }
};
return json;
}
Either rename your class properties to match your JSON, rename your JSON to match your class properties, or implement a custom JsonConverter, where you can implement arbitrary mapping.
I am getting response in the format of JObject which is like this.
JObject response = JObject.Parse(account);
{
"status": 1,
"msg": "1 out of 1 Transactions Fetched Successfully",
"transaction_details": {
"ae6df74457a7cbf62caf": {
"mihpayid": "403993715518647003",
"request_id": "",
"bank_ref_num": "201833147408756",
"amt": "88.00",
"transaction_amount": "88.00",
"txnid": "ae6df74457a7cbf62caf",
"additional_charges": "0.00",
"Settled_At": "0000-00-00 00:00:00"
}
}
}
Now the "transaction_details" that value ("ae6df74457a7cbf62caf") rapidly change every transaction,So how i get that value and after that how I get "mihpayid" key value in C#.
You need to create a class to represent the JSON being returned.
The transaction_details part of the object can be represented as a Dictionary for example:
class Account
{
public int Status { get; set; }
public string Msg { get; set; }
public Dictionary<string, TransactionDetails> transaction_details { get; set; }
}
class TransactionDetails
{
public string mihpayid { get; set; }
public string requestid { get; set; }
public string bank_ref_num { get; set; }
public string amt { get; set; }
public string transaction_amount { get; set; }
public string txnid { get; set; }
public string additional_charges { get; set; }
public string Settled_At { get; set; }
}
And, instead of using JObject.Parse(...) use the JsonConvert.DeserializeObject to convert the JSON into your C# class:
var myData = JsonConvert.DeserializeObject<Account>(account);
You can now reference all the properties of your JSON using the myData object.
You can loop through the transaction_details reading each entry.
foreach(var item in myData.transaction_details)
{
var id = item.Key;
var transaction = item.Value;
var mihpayid = transaction.mihpayid;
}
The values of the variables in the for loop are:
id = the unique ID for each transaction i.e. "ae6df74457a7cbf62caf"
transaction = a Transaction object with all the values from the unique transaction
mihpayid = the mihpayid within the unique transaction i.e. "403993715518647003"
JObject response = JObject.Parse("{\r\n \"status\": 1,\r\n \"msg\": \"1 out of 1 Transactions Fetched Successfully\",\r\n \"transaction_details\": {\r\n \"ae6df74457a7cbf62caf\": {\r\n \"mihpayid\": \"403993715518647003\",\r\n \"request_id\": \"\",\r\n \"bank_ref_num\": \"201833147408756\",\r\n \"amt\": \"88.00\",\r\n \"transaction_amount\": \"88.00\",\r\n \"txnid\": \"ae6df74457a7cbf62caf\",\r\n \"additional_charges\": \"0.00\",\r\n \"Settled_At\": \"0000-00-00 00:00:00\"\r\n }\r\n }\r\n }");
JObject transaction = JObject.Parse(response["transaction_details"].ToString());
foreach(var token in transaction.Properties())
{
var rapidlyChangingId = token.Name;
Console.WriteLine("Rapidly Changing ID: " + rapidlyChangingId);
Console.WriteLine(transaction[rapidlyChangingId]);
}
OUTPUT:
Rapidly Changing ID: ae6df74457a7cbf62caf
{
"mihpayid": "403993715518647003",
"request_id": "",
"bank_ref_num": "201833147408756",
"amt": "88.00",
"transaction_amount": "88.00",
"txnid": "ae6df74457a7cbf62caf",
"additional_charges": "0.00",
"Settled_At": "0000-00-00 00:00:00"
}
You can use JObject and convert it to C# object. Something like this:
How to deserialize an JObject to .NET object
I am trying to create a json string to send via a httprequest, I have json string like so:
{
"a-string": "123",
"another-string": "hello",
"another": "1"
}
My problem is, if I try and generate it like so
string json = new JavaScriptSerializer().Serialize(new
{
"a-string" = "123",
"another-string" = "hello",
"another" = "1"
});
Leads to:
So what is a way of trying to do the above, without getting that error?
Use Json NewtonSoft NuGet package. Then use my answer here to create a C# class for you json. Since your json has names in them which are not allowed as property names in C#, you can use the JsonPropety attribute so it can use it during serialization. Here is all of the code:
public class Rootobject
{
[JsonProperty("a-string")]
public string astring { get; set; }
[JsonProperty("another-string")]
public string anotherstring { get; set; }
public string another { get; set; }
}
public class Program
{
public static void Main()
{
var root = new Rootobject { another = "1", anotherstring = "hello", astring = "123" };
string json = JsonConvert.SerializeObject(root);
Console.Read();
}
}