Get initial JSON representation of ConfigurationSection - c#

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

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);
}

Manipulating JSON String in C# without Object

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.

Search for one key in multi-level JSON array

I receive JSON output from several different web services. I need to obtain some token data from each service however it's in a different array each time. E.g.:
Service 1:
{
"service_name": "service1",
"service1_data": {
"token_data": "WSD123456789"
}
}
Service 2:
{
"service_name": "service2",
"service2_data": {
"token_data": "QSD76662345"
}
}
So I'm looking for a way to search for the value of "token_data" no matter where in the arrays it may be. At the moment I have to get it manually like so:
json1["service1_data"]["token_data"]
If theres a simple way to do this it would be much appreciated. Thanks!
You could convert the JSON to XML and then use an xpath like '//token_data' to find the token, assuming a simple string search or regex is not an option.
byte[] bytes = Encoding.ASCII.GetBytes(json);
using (var stream = new MemoryStream(bytes))
{
var quotas = new XmlDictionaryReaderQuotas();
var jsonReader = JsonReaderWriterFactory.CreateJsonReader(stream, quotas);
var xml = XDocument.Load(jsonReader);
}
Xpath info can be found here
As suggested in the comments, you could use JSONPath.
In your scenario, $.service1_data.token_data.* should get you all the values you want.
This works only if the depth of token_data in the array is always the same.
The Newtonsoft.Json package - available on NuGet Install-Package Newtonsoft.Json allows you to walk Json objects using LINQ expressions.
var jsonText = #"{
""service_name"": ""service1"",
""service1_data"": {
""token_data"": ""WSD123456789""
}
}";
var jsonObject = JsonConvert.DeserializeObject<JToken>(jsonText);
System.Diagnostics.Debug.Assert(jsonObject["service1_data"].Value<string>("token_data") == "WSD123456789");
See the JToken reference to learn how to retrieve values from Json.

Query JSON With Unknown Structure

We are trying to write a way to consume a JSON feed from a third party but unfortunately it's not well written, there appears to be no rules on what is sometimes there or not and also the structure changes depending on the key, I have no way of changing this we have to work with what we have. We know what we want based on certain keys but we are struggling to find them as the nested structure changes.
Is it possible to flatten the JSON down to a single List> that we can query and the key would be the fully qualified name including parents so the following JSON:
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
Would become a list with keys like:
"employees.firstName" and a value of "John".
I think if we could get to this we could query the data for what we want, we have been trying to use dynamic objects but as I said the JSON changes and properties are missing sometimes and it's proving impossible to handle all scenarios.
If you don't know reliably the structure of a JSON but you are sure about property name ex "firstName". You can use the JSON.NET JObject and recursively loop through it and check if the property you are looking for exists in the current JToken.
The code should look something Like that, note the code I didn't compile it can have some typing mistakes:
private List<string> LoadFirstNames(string json)
{
JObject o = JObject.Parse(json);
List<string> firstNames = new List<string>();
foreach(var token in o.GetPropertyValues())
{
FindFirstName(token, firstNames);
}
return firstNames;
}
private void FindFirstName(JToken currentProperty, List<string> firstNamesCollection)
{
if(currentProperty == null)
{
return;
}
if(currentProperty["firstName"] != null)
{
firstNamesCollection.Add(currentProperty["firstName"]);
}
foreach(var token into currentProperty.Values())
{
FindFirstName(token , firstNamesCollection);
}
}

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