Manipulating JSON String in C# without Object - c#

I have JSON String which I am reading from file.
I don't have the source of the JSON Object.
So I can't call JsonConvert.DeserializeObject.
However I want check if the JSON String has specific structure, if yes, append some string or If not append the structure.
allmodules {
feature: 'test-a'
}
submodules {
//some data
}
Assume if there's not allmodules, I would like to append my structure
allmodules {
feature: 'debug-a'
}
If it's already available, just append feature: 'debug-a'
And so on I have some custom work to do. Is there any efficient way to do this without breaking JSON format. Most of the questions regarding String to Object de-serialization, however as I mentioned I don't have original Object, and can't do that.

You can do this using JObject and doing a little manual parsing. It could look something like this:
public string AppendAllModules(string json)
{
var obj = JObject.Parse(json);
JToken token;
if (obj.TryGetValue("allmodules", out token))
return json;
obj.Add(new JProperty("allmodules", new JObject(new JProperty("feature", "test-a"))));
return obj.ToString();
}
Given:
{
"submodules": {
"name": "yuval"
}
}
Would yield:
{
"submodules": {
"name": "yuval"
},
"allmodules": {
"feature": "test-a"
}
}

I don't have the source of the JSON Object.
No worries, you can simply construct a new C# object that it compatible with the JSON definition. There are a number of options listed at
How to auto-generate a C# class file from a JSON object string
Once you have a compatible C# class in your project, you can deserialize the JSON and manipulate it as an object, just as if you had the original object.

use either JObject.FromObject or JObject.Parse to get your file json string into a JObject.
Then the below example code may help. I am going via an If/else way because you mentioned you can not get the exact structure.
JObject obj = JObject.FromObject(
new {Id = 5, Name = "Foo"}
);
JToken jtok = null;
bool found = obj.TryGetValue("Bar",StringComparison.CurrentCultureIgnoreCase, out jtok);
if (!found)
{
obj.Add("Bar","this is added");
}
else
{
Console.WriteLine(jtok);
}
Console.WriteLine(obj["Bar"]);
Of course after you are done editing your JObject you can use the JObject.ToString() method to get the string representation and send it over to the file.

Related

Get Key Name from nested json object

I am new to C# and JSON and need some help in getting the Key name(s) in a list of a nested JSON object. The keys are dynamic so I won't necessarily know the keys.
sample code I've tried.
```
protected void test()
{
var mystring = #"{
""zone1"": {
""sites"": {
""site1"": {
""to"": ""email1"",
""subject"": ""subjecttxt"",
""link"": ""somesite""
},
""site2"": {
""to"": ""email1"",
""subject"": ""subject"",
""link"": ""somesite""
}
},
""zone2"": {
""to"": ""email1"",
""subject"": ""subject"",
""link"": ""somelink""
}}";
var rss = JObject.Parse(mystring);
foreach (var section in rss)
{
Console.Write(section.Key);
IList<JToken> result = rss["zone1"]["sites"].Children().ToList();
var zone = section.Key;
var site = rss[zone]["sites"];
foreach (var subsite in rss["zone1"]["sites"])
{
var subs = subsite.Parent.ToString();
// some other code
}
}
}
```
Looking for a result:
site1,
site2,
...
I can get the children as IList but looking for something similar to "section.Key" as noted above.
Thank you for your help.
I believe what you are looking for is to get the properties of the sites. Since accessing the rss["zone1"]["sites"] returns a JToken, you will need to convert that to JObject and then use Properties() method to get the data you need.
var sites = ((JObject)rss["zone1"]["sites"]).Properties();
Then you can simply iterate over the IEnumerable<Jproperty> to get the Name of the property or whatever else you need from under it.
To get the section.Key for the sites, you can use the following code.
foreach(var site in (JObject)rss["zone1"]["sites"]) {
Console.WriteLine(site.Key);
}
Output:
site1
site2
Your first call to JObject.Parse already does all the work of converting a string into a structured JSON object. The currently-accepted answer redoes some of this work by (1) turning a structured JSON object back into a string, and then (2) re-parsing it with JObject.Parse. There is a simpler way.
Instead, you can cast the value stored at rss["zone1"]["sites"] into a JObject. (The expression rss["zone1"]["sites"] has type JToken, which is a parent class of JObject, but in this case we happen to know that rss["zone1"]["sites"] is always JSON object, i.e. a collection of key-value pairs. Therefore, this cast is safe to perform.)
This is what the code might look like:
var sites = (JObject) rss["zone1"]["sites"];
foreach (var site in sites)
{
Console.WriteLine(site.Key);
}

Get initial JSON representation of ConfigurationSection

Let's assume we have this section in appsettings.json
{
"crypto":{
"A": "some value",
"B": "foo foo",
"C": "last part"
},
...
}
Where "crypto" is json serialization of some cryptographic key.
Later in the code, I need to make something like this:
var keyOptions = CryptoProvider.RestoreFromJson(Configuration.GetSection("crypto"))
But Configuration.GetSection return ConfigurationSection instance. Is there a way to get raw json data behind it somehow?
I assumed that ConfigurationSection.Value should do the trick, but for some reason it's always null.
Here is an example impelementaion.
private static JToken BuildJson(IConfiguration configuration)
{
if (configuration is IConfigurationSection configurationSection)
{
if (configurationSection.Value != null)
{
return JValue.CreateString(configurationSection.Value);
}
}
var children = configuration.GetChildren().ToList();
if (!children.Any())
{
return JValue.CreateNull();
}
if (children[0].Key == "0")
{
var result = new JArray();
foreach (var child in children)
{
result.Add(BuildJson(child));
}
return result;
}
else
{
var result = new JObject();
foreach (var child in children)
{
result.Add(new JProperty(child.Key, BuildJson(child)));
}
return result;
}
}
If you want to get content of crypto section, you can use
Configuration.GetSection("crypto").AsEnumerable()(or for your example Configuration.GetSection("crypto").GetChildren() may be useful).
But the result is not raw json. You need to convert it.
I may not have get the question nor the context right, but if you want to work with raw json or json token, you may should use the Newtonsoft library.
As exemple, admitting that Configuration is an object, you may use JsonConvert.SerializeObject() in order to transform your object in a JSON string (it also work the other way round). You can also work with the JObject library which is provided in the same packet, and which contain LINQ tools.
For exemple, the below code just read your json file wich contain the given serialize object, and load into a .Net object.
String filecontent = "";
StreamReader s = new StreamReader(file.OpenReadStream());
filecontent = s.ReadToEnd();
contractList = JsonConvert.DeserializeObject<YourObject>(filecontent);
I really don't know if I get it right, but the question confused me. For exemple, could you precise how you load your json ? Which type is the object where yo ustore it (the Configuration one I gess ?) ? Etc....

Easily working on a json object

I'm deserializing (or parsing) a json string to a c# object (using Json.NET) and getting a JObject. I want to iterate all the properties with the key "bla", in the same way iterating all xml elements that named "bla" with XElement.Elements("bla").
If it's not possible, I would like to deserialize my json string into a c# object, and work dynamically and recursively on my deserialized json object (my json string can have lists / arrays that can have objects of 2 types.
In the end after editing my object (changing values and removing or adding properties) I need to serialize my object back to a json string.
Which is the best and easiest way to use json serializing and deserializing?
my Json looks like this:
{"Families":{"Family":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}, {"propA":"dhsj", "propB":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}, {"propA":"dhsj", "propB":"fghfgh"}]}]}
in conclusion, the json value is a json object that it's value is a list/array, the list/array can contain 2 "types" of objects, and one of these types also has a property which it's value is a json object that it's value is a list/array, and it goes like this recursively. sometimes the value of one of the props of the type that doesn't have a property which it's value is a json object that it's value is a list/array, can be a list/array itself, that can contain only 1 type of the two mentioned.
If you don't need a strongly-typed object, you can deserialize to a dictionary:
Dictionary<string, object> myObject = JsonConvert.DeserializeObject<Dictionary<string, object>>(jsonString);
And then just use it as a dictionary:
myObject["Property"] = value;
Or
foreach(var propertyKey in myObject.Keys)
{
// do something with each property
Console.WriteLine($"{propertyKey} = {myObject[propertyKey]}");
}
Here's a fiddle
You can serialize it back after you are done
My json looks more like this:
{"Familys":{"Family":[{"propA":"dhsj", "propB":"dhdisb"}, {"propA":"krbsbs", "propC":"ksndbd", "propD":"odndns", "Families":{"Family":[....]}}]}
For JSON like this:
var json = #"{
""Families"":{
""Family"":[
{
""propA"":""Top""
},
{
""propA"":""Top.Lower"",
""Families"":{
""Family"":[
{
""propB"":""propB value""
},
{
""propA"":""Top.Lower.EvenLower"",
""Families"":{
""Family"":[
{
""propA"":""Top.Lower.EvenLower.EvenLower""
}
]
}
}
]
}
}
]
}
}";
Do something like this:
//calling code makes use of "dynamic" to make things clean and readable.
dynamic parsedJson = JsonConvert.DeserializeObject(json);
var allPropAValues = GetPropAValues(parsedJson);
//**** NOTE: this has our extra property ****
var jsonWithExtraStuffProperty = JsonConvert.SerializeObject(parsedJson);
//recursive function that reads AND writes properties
public static List<string> GetPropAValues(dynamic obj)
{
var propAValues = new List<string>();
//**** NOTE: the use of an added property ****
obj.ExtraStuff = new Random().Next();
//if we have a propA value, get it.
if (obj.propA != null)
propAValues.Add(obj.propA.Value);
//iterate through families if there are any. your JSON had Families.Family.
if (obj.Families != null)
foreach (dynamic family in obj.Families.Family)
propAValues.AddRange(GetPropAValues(family));
return propAValues;
}

How to create a json string where a property contains a dot (period)?

I'm trying to send an HttpRequest that takes a JSON object like this:
{
"some.setting.withperiods":"myvalue"
}
I've been creating anonymous objects for my other requests, but I can't do that with this one since the name contains a dot.
I know I can create a class and specify the [DataMember(Name="some.setting.withperiods")] attribute, but there must be a more lightweight solution.
There is no "easy" way to achieve this because the . in C# is reserved.
However, you could achieve something pretty close by using a dictionary and collection initializer. It's still somewhat isolated, and doesn't require you to create a custom class.
var obj = new Dictionary<string, object>
{
{ "some.setting.withperiods", "myvalue" }
};
var json = JsonConvert.SerializeObject(obj);
//{"some.setting.withperiods":"myvalue"}
You can use "JsonProperty" attribute for the same For example
[JsonProperty(".Name")]
public string Name { get; set; }
On top of this I want to add how to retrieve the data from the json where it has name property starting with special character as in Web API 2.0 token has ".issued".
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
var jsonRespons="json response from the web api";
var issue= JObject.Parse(jsonResponse).GetValue(".issued");
if you do it from in javascript, you can easily go back and forth, as shown with:
var obj = {
"some.setting.withdots":"myvalue"
};
var json = JSON.stringify(obj);
console.log(json);
var str = JSON.parse(json);
console.log(str);
have you tried putting it into a serialized string and sending that, then deserializing on the client-side?
you could do something like
var myAnnon = new
{
WithPeriod = "value"
};
var j = JsonConvert.SerializeObject(myAnnon);
j = j.Replace("WithPeriod", "some.setting.withdots");
You can use a JObject (part of Json.Net's LINQ-to-JSON API) to create the JSON in question:
string json = new JObject(new JProperty("some.setting.withperiods", "myvalue")).ToString();
Fiddle: https://dotnetfiddle.net/bhgTta
You could try prefixing your member names with a # to allow use of literals, but the way to do it is using [DataMember] as you have already mentioned in your question.

JavaScriptSerializer: Serialize a list + a string into JSON

I want to use JavaScriptSerializer to send a package of JSON data that contains both a list of objects as well as a string, identified like ChatLogPath. As far as I can tell, that class can only serialize one object -- being the list -- and if I try to append multiple ones it obviously just creates invalid JSON like {...}{...} which won't work.
Is there any way to do this? I'm insanely new to C# and ASP.NET MVC so forgive me if this is a dumb question :)
Edit: here's my code as of right now.
string chatLogPath = "path_to_a_text_file.txt";
IEnumerable<ChatMessage> q = ...
...
JavaScriptSerializer json = new JavaScriptSerializer();
return json.Serialize(q) + json.Serialize(chatLogPath);
Which will output the array like this in JSON { ... } followed by the chatLogPath { ... }. In other words, it can't work since that's invalid JSON.
The easiest way to get a single JSON object with the array and path together is to create a class or dynamic object with each as a property/field of it.
Class example:
public class ChatInformation {
public IEnumerable<ChatMessage> messages;
public string chatLogPath;
}
...
var output = new ChatInformation {
messages = ...,
chatLogPath = "path_to_a_text_file.txt"
};
return json.Serialize(output);
Dynamic example (requires .NET 4+):
dynamic output = new ExpandoObject {
messages = ...,
chatLogPath = "path_to_a_text_file.txt"
};
return json.Serialize(output);
Anonymous Type example (if you don't care to have another class, nor are you on .NET 4):
var output = new {
messages = ...,
chatLogPath = "path_to_a_text_file.txt"
};
return json.Serialize(output);

Categories