I have a business case where I need to take any incoming JSON payload (so the JSON object will have to be dynamic, not predefined by a C# class) and prepend a given namespace to all its containing keys.
For example if the following payload comes in:
{
"property1": "value1",
"property2": 2,
"property3": true,
"property4": {
"myArray": [
{
"arrayProperty1": "im the first object in array",
"arrayProperty2": "some value"
},
{
"arrayProperty1": "im the second object in array",
"arrayProperty2": "some value"
}
]
}
}
Then it needs to result in the following output:
{
"mynamespace.property1": "value1",
"mynamespace.property2": 2,
"mynamespace.property3": true,
"mynamespace.subObj": {
"mynamespace.myArray": [
{
"mynamespace.arrayProperty1": "im the first object in array",
"mynamespace.arrayProperty2": "some value"
},
{
"mynamespace.arrayProperty1": "im the second object in array",
"mynamespace.arrayProperty2": "some value"
}
]
}
}
Is this possible using C#? I tried searching for any similar question here on stackoverflow but this is the closest I got (they're using javascript): Prepending namespace to all of a JSON object's Keys
You can make a short helper method using Json.Net's LINQ-to-JSON API (JTokens) to accomplish this:
public static string AddPrefixToAllKeys(string json, string prefix)
{
JContainer token = (JContainer)JToken.Parse(json);
// Note: We need to process the descendants in reverse order here
// to ensure we replace child properties before their respective parents
foreach (JProperty prop in token.Descendants().OfType<JProperty>().Reverse().ToList())
{
prop.Replace(new JProperty(prefix + prop.Name, prop.Value));
}
return token.ToString();
}
Then use it like this:
string modifiedJson = AddPrefixToAllKeys(originalJson, "mynamespace.");
Working demo here: https://dotnetfiddle.net/AdkAO7
Related
I have a little utility where we extract values from JSON using JObject.SelectToken(path). We need to determine the paths at run-time. Works perfectly.
What I now need to do is to write back into the JSON (JObject or other) using the same path string. I've hunted and searched and I can't quite find if there is anything that does this quite as cleanly as SelectToken does for reading.
(I'm also stuck in 3.5 CF)
For example, something like:
... JObject read in already ...
var theJToken = theJObject.SelectToken("animals.cat[3].name");
theTJoken.SetValue("Bob"); // Of course this doesn't exist
... serialize it ...
JToken.SelectToken actually returns a JToken which can be modified using JToken.Replace. You can use that to replace the node within your JSON object, mutating the original object.
JObject o = JObject.Parse(#"{ 'cats': [
{ 'name': 'cat 1' },
{ 'name': 'cat 2' },
{ 'name': 'cat 3' } ] }");
// get the token
JToken secondCatName = o.SelectToken("cats[1].name");
// replace the name
secondCatName.Replace("meow");
// and the original object has changed
Console.WriteLine(o.ToString());
// { "cats": [ { "name": "cat 1" }, { "name": "meow" }, { "name": "cat 3" } ] }
I have a simple JSON example like this :
{
"items": {
"element": ["item 1","item 2"]
},
"name": "James"
}
and a JSON Schema like this :
{
'type': 'object',
'properties': {
'name': {'type':'string'},
'items': {
'type': 'object',
'properties':{
'element':{
'type':'array',
'items':[{'type':'string', 'type':'string'}]
}
}
}
},
'additionalProperties': false
}
Calling "IsValid()" method in JSON.NET using the given Schema and Data will return VALID.
Question :
How do I traverse and edit the elements inside JSON ?
My objective is to look-up values of node "element" in database and then replace it with a generalized value if they exists e.g "item 1" exists in database and will replaced with "general value A". However, "item 2" doesn't exist in database and should throw some kind of error message when IsValid() method is called.
Note that this is a desktop application using .NET 4.5 and JSON.NET library, and it will be used as a data-cleansing tool. I'm open to any kind of alternative libraries as long as they are compatible with .NET 4.5 though..
Not fully understand the part of your question with IsValid() issue, but if talk about traversing through json elements and editing, you can use 2 methods.
Install Newtonsoft.Json at first in Package-Manager in VS: Install-package newtonsoft.json.
Create class JsonItems, which describes your input JSON hierarchy
class JsonItems
{
public Items items;
public string name;
}
class Items
{
public List<string> elements { get; set; }
}
Now you can legally deserialize your json and edit result as any .net object.
string jsonItems = #"{
'items': {
'element': ['item 1','item 2']
},
'name': 'James'
}";
var result = JsonConvert.DeserializeObject<JsonItems>(jsonItems);
result.items = new Items
{
elements = new List<string> {"itemd 3", "item 4"}
};
2. The second way is more quick (in implementation), but less secuarble in runtime. With help of dynamic.
dynamic d = JObject.Parse(jsonItems);
d.items.element[1] = "item 3";
I have a valid JSON object that contains multiple "en-US" keys, which I'm trying select. For that purpose I use the JsonPath
"$..en-US"
which is given to the SelectTokens procedure implemented by the Json.NET. It's a JSON framework for .NET . Everything is working fine and well as long as my JSON doesn't contain any empty array.
Here's an example:
var myJsonPath = "$..en-US";
var myJson =
#"{
'controls': [
{
'messages': {
'addSuggestion': {
'en-US': 'Add'
}
}
},
{
'header': {
'controls': []
},
'controls': [
{
'controls': [
{
'defaultCaption': {
'en-US': 'Sort by'
},
'sortOptions': [
{
'label': {
'en-US': 'Name'
}
}
]
}
]
}
]
}
]
}";
var jToken = JObject.Parse(myJson);
var tokens = jToken.SelectTokens(myJsonPath);
Here, the tokens variable will contain just one element! That will be the "en-US" occurence BEFORE the empty array in the 'controls' of the 'header' object. However, when I just leave this 'header' object out:
var myJson =
#"{
'controls': [
{
'messages': {
'addSuggestion': {
'en-US': 'Add'
}
}
},
{
'controls': [
{
'controls': [
{
'defaultCaption': {
'en-US': 'Sort by'
},
'sortOptions': [
{
'label': {
'en-US': 'Name'
}
}
]
}
]
}
]
}
]
}";
I will get all the 3 occurencies of the "en-US" as expected. Btw, if I validate my JsonPath on the first JSON object (i.e. which contains an empty array) in an online tool, then as expected, I get all the three "en-US" cases. This diverges from what I'm getting from the Json.NET. I'm wondering whether it's a bug or do I have to handle this case manually somehow?
This is a bug that has been fixed. Upgrade to the latest version of Json.NET.
If you're in the same situation as me where you're a bit stuck with respect to updating your version of Json.NET, you can work around the issue by doing something along the lines of this:
IEnumerable<JValue> vals = jToken
.Desecendants()
.Where(w => w is JProperty && w.Name=="en-US")
.Select(s => s.Value);
Hope that helps! The vals array will contain the same tokens you would have gotten using the selector you were trying to use before.
I have a C# class which contains a property of Dictionary
I have a web-page which contains a list of items i need to cast into this dictionary.
My web-site will send the list up to my C# MVC application as JSON and then JsonConvert.Deserialise the JSON into my Dictionary object.
JsonConvert.Deserialise is expecting JSON in the following format:
"MyVariableName":{
"Item 1":true,
"Item 2":true
}
I need to know how i can construct this object in JavaScript.
So far, i have tried this without luck:
var items = [];
var v = $('#Items :input');
$.each(v, function(key, val) {
items.push({
key: val.value,
value: val.checked
});
});
JSON.stringify(v, null, 2);
But this returns a json converted value of:
"MyVariableName": [
{
"key": "Item 1",
"value": true
},
{
"key": "Item 2",
"value": true
}]
Which in turn does not de-serialize to my dictionary.
Thanks
Don't make an array; make an object:
var items = {};
$('#Items :input').each(function(i, val) {
items[val.value] = val.checked;
});
You have to use javascript serialization
One more thing you have different value int key, value pair like string and Boolean type, so you have to use Dictionary type.
And JavaScriptSerializerobject you will get System.Web.Script.Serialization name space of System.Web.Extensions.dll, v4.0.30319 assembly.
var jSerializer = new JavaScriptSerializer();
var newList= jSerializer.Deserialize<Dictionary<string,object>>(newData);
I'm trying to generate JSON using C# and DataContractJsonSerializer in .Net 3.5. The problem is that I can't figure out how to build the structure correct for the result I need.
I've tried to reproduce PHP's associative arrays using both hashtables, list objects and arraylists but can't figure out how to generate my result in the best way using DataContractJsonSerializer without having to create my own recursive loop for building JSON.
The closest approach is using the a Dictionary < string, Dictionary < string, string>> aproach but the result is too big as I can't "name" the keys.
This is what I get:
[
{
"Key":"status",
"Value":[
{
"Key":"value",
"Value":"ok"
}
]
},
{
"Key":"1",
"Value":[
{
"Key":"name",
"Value":"Result1"
},
{
"Key":"details",
"Value":"Result 1 details"
}
]
},
{
"Key":"2",
"Value":[
{
"Key":"name",
"Value":"Result2"
},
{
"Key":"details",
"Value":"Result 2 details"
}
]
},
{
"Key":"caller",
"Value":[
{
"Key":"value",
"Value":"1135345"
}
]
}
]
This is what I want:
{
"status":"ok",
"response":[
{
"id":1,
"name":"Result1"
"details":"Result 1 details"
},
{
"id":2,
"name":"Result2"
"details":"Result 2 details"
},
{
"id":3,
"name":"Result3"
"details":"Result 3 details"
],
"caller":"1135345"
}
Does anybody have a clue how I can generate this piece of JSON using C# without having to load the entire Json.NET framework? I need this to be generated as fast as possible as this project aims to become an site search engine.
You should look at using the JavaScriptSerializer. It's part of the .NET framework (distributed in System.Web.Extensions). To get the result you want you can do this:
var results = new[]
{
new{id=1,name="Result 1"},
new{id=2,name="Result 2"},
new{id=3,name="Result 3"}
};
var js = new JavaScriptSerializer();
var result = js.Serialize(new
{
status = "ok",
response = results,
caller = 1135345
});
You can either use anonymous classes, or any existing ones. Works perfectly fine :)
The return value of this call would be:
{"status":"ok","response":[{"id":1,"name":"Result 1"},{"id":2,"name":"Result 2"},{"id":3,"name":"Result 3"}],"caller":1135345}
Using the JavaScriptSerializer rather than DataContractJsonSerializer on a Dictionary will remove the Key/Value json attributes and make them into a "keyed" array.
http://msdn.microsoft.com/en-us/library/bb412168.aspx
Have you attributed your classes with the [DataContract] and [DataMember] decorators?
http://msdn.microsoft.com/en-us/library/bb412179.aspx