I have a 'simple' scenario: Read some JSON file, Filter or change some of the values and write the resulting json back without changing the original formatting.
So for example to change this:
{
"type": "FeatureCollection",
"crs": {
"type": "EPSG",
"properties": {
"code": 28992
}
},
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
149886.192,
374554.705
],
[
149728.583,
374473.112
],
[
149725.476,
374478.215
]
]
]
}
}
]
}
Into this:
{
"type": "FeatureCollection",
"crs": {
"type": "EPSG",
"properties": {
"code": 28992
}
},
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates":
[
149886.192,
374554.705
]
}
}
]
}
I've tried JSON.Net by newtonsoft among others but the only this I can find is:
read into object
write object to json
But I'm missing the 'change the object' step. Any hints?
Update
Here's what I've tried so far:
JToken contourManifest = JObject.Parse(input);
JToken features = contourManifest.SelectToken("features");
for (int i = 0; i < features.Count(); i++)
{
JToken geometry = features[i].SelectToken("geometry");
JToken geoType = geometry.SelectToken("type");
JToken coordinates = geometry.SelectToken("coordinates");
geoType = "Point";
}
But this only changes the value of the geoType variable. I'd expected to change the value inside the geometry as well. I need a reference, not a copy! Is this possible?
Update
I am currently off this project but I'd like to give my feedback to the answerers. Though I like the simplicity of Shahin, I like the more formal approach of L.B. a bit better. I personally don't like using string values as functional code, but that's just me. If I could accept both answers: I would. I guess Shahin wil have to make due with 'just' an upvote.
dynamic contourManifest = JObject.Parse(input);
foreach (var feature in contourManifest.features)
{
feature.geometry.Replace(
JObject.FromObject(
new {
type = "Point",
coordinates = feature.geometry.coordinates[0][0]
}));
}
var newJson = contourManifest.ToString();
I know this has already been answered but I thought I had a solution others might find interesting.
I had a pretty large stringified JSON object that I received from a customer and needed to manipulate in C# and then return in string form back to the calling application.
It didn't make sense to model every aspect of the object, many parts that I wasn't planning on manipulating were changing often and I couldn't be expected to update my application every time the caller modified portions of their JSON object I wasn't being asked to manipulate. So I tried this, it's a bit ugly but it worked well:
Create a class (myClass) representing just the section you want to manipulate.
Using Newtonsoft, create a dynamic version of the stringified JSON object:
dynamic jsonObj = JsonConvert.DeserializeObject(stringifiedJsonObject);
Build your replacement object using the class you created above (myClass). Then serialize that object using
string stringPartialJsonObj = JsonConvert.SerializeObject(myClass);
Next, (and this is the trick) deserialize the object you just created. Now it's the same type as your source.
dynamic partialJsonObj = JsonConvert.Deserialize(stringPartialJsonObj);
Imagine (for the sake of this demonstration) in the original Json object, I needed to modify the object in obj.ConfigurationData.Configuration1.Data. This is how I'd do it:
jsonObj.ConfigurationData.Configuration1.Data = partialJsonObj;
Finally, I'd re-serialize the whole thing and send it back to the user:
return JsonConvert.SerializeObject(jsonObj);
It's a bit clunky, but it works. Story of my life :-)
If you don't want using any entity that representing your JSON, you can deserialize to Dictionary by using json.net and modify dictionary, then serialize it to JSON by using Json.net.
Using Json.net you have to create the entities representing your json
Deserialize the json into those enties like Json.Convert<FeatureCollection>(json)
Change the entities
Convert it back to json.
Related
There is a nice function in json.net to convert a json into a c# object:
CMyObject myObject = Newtonsoft.Json.JsonConvert.DeserializeObject<CMyObject>(json);
Problem with that is that the structure needs to be known upfront.
Is there a lean way if the structre itself is coming from json itself?
Here an example of the json:
{
"data": {
"255622": {
"2": {
"value": "Active"
},
"3": {
"value": null
}
}
},
"schema": {
"255622": {
"name": "NameOfStructure",
"properties": {
"2": {
"multi_value": false,
"name": "Status",
"type_name": "String"
},
"3": {
"multi_value": false,
"name": "StatusDate",
"type_name": "Date"
}
}
}
}
}
This should convert to:
myObject (type NameOfStructure)
myObject.Status = "Active" (type String - single value)
myObject.StatusDate = null (type Date - single value)
Any ideas?
actually I am pretty sure you can do that with the dynamic keyword.
I can't check right now but you should be able to do something like :
dynamic myObject = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
or something along those lines, this is sometimes useful as you can still parse the tree for whatever you need or discover what the types are and then do something with that information, depending on your use case.
I also used another approach in the past with an ExpandoObject instead of dynamic.
It depends what your use case is, but those are the approaches I'd investigate more
With json.net you can easily do like this:
dynamic myObject = JsonConvert.DeserializeObject(json);
The result will be dynamic so you can reach any property by
var myField = myObject.data.yourJsonfield;
Also same with using Newtonsoft.Json.Linq:
dynamic myObject = JObject.Parse(json);
You can find more information here.
I wish to write some C# which allows the client to provide a JSON string and query string. The query string would then be used to address values in the JSON object.
For example, if I had this JSON:
{
"head": "big",
"fingers": [
"one", "thumb",
"two", "ring"
],
"arm": {
"elbow", "locked"
}
}
And this query string:
"fingers.two"
I would want to return the value "ring".
Is this (or something like it) possible in C#?
I have tried using the ExpandoObject class, but this does not allow dynamic runtime inspection:
var json = JsonConvert.DeserializeObject<ExpandoObject>(jsonStr);
As far as I can tell, the discovery of values on the json variable needs to be done at code time, rather than runtime, which means I cannot dynamically find values being queried for.
JSONPath does this
Assuming the following JSON (fixed a few syntax errors in the original)
{
"head": "big",
"fingers": {
"one":"thumb",
"two":"ring"
},
"arm": {
"elbow": "locked"
}
}
And this query
MyJObjectOrToken.SelectToken("fingers.two")
You will get the following output:
[
"ring"
]
It should be trivial then to extract the value as a string using JSON.Net methods and return the result to your user.
Support for JSONPath is built into JSON.Net
https://www.newtonsoft.com/json/help/html/SelectToken.htm
All attempts to use JsonUtility.FromJson on a json with nested values fail.
How would you turn the following json into an object without creating a class for every nested value?
{
"Player": {
"Level": 1
},
"Weapons":{
"BasicWeapon": {
"Level": 1
}
}
}
use SimplJson Library Like this
JSONNode node = JSON.Parse( jsonString );
string level= node["Player"]["Level"].Value;
there is also another Library that can Handle that :
https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347
[{"id":"PROCESS_ROOT_NODE","text":"TEMPLATE - 3333(2)","icon":"fa fa-list fa-color-graylt","li_attr":{"id":"PROCESS_ROOT_NODE","__type":"li_attr:#SomeNamespace.JsonDataContractClasses","class":" ps_node_li "}}]
I slimmed the object down alot.
Basically when the '__type' is not in the first position, before 'id'. The deserialize will throw an error.
I have all the DataContract stuff setup correctly, with known types.
I've tested in a console app, serializing, then taking that string back thru the deserialize and it works perfectly. The only difference is the location of the '__type'. This is a known MS issue.
Documented at https://msdn.microsoft.com/en-us/library/bb412170(v=vs.110).aspx
Tried a string replace, which does work. and the DataContractJsonSerializer did not care if '__type' key was in there twice.
content = content.Replace("\"li_attr\":{", "\"li_attr\":{\"__type\":\"li_attr:#Payce.Common.AnonymousClasses.JsonDataContractClasses\",");
Just looking for the best way to move the __type to the first position.
You can use Json.Net to manipulate your json
var jArr = JArray.Parse(jsonstring);
var attrs = jArr.Select(x => x["li_attr"]).ToList();
attrs.ForEach(attr =>
{
var type = attr["__type"].Parent;
type.Remove();
(attr as JObject).AddFirst(type);
});
var newjson = jArr.ToString(Newtonsoft.Json.Formatting.Indented);
Output of this code is
[
{
"id": "PROCESS_ROOT_NODE",
"text": "TEMPLATE - 3333(2)",
"icon": "fa fa-list fa-color-graylt",
"li_attr": {
"__type": "li_attr:#SomeNamespace.JsonDataContractClasses",
"id": "PROCESS_ROOT_NODE",
"class": " ps_node_li "
}
}
]
But I would recommend to use Json.Net all the way instead of just converting your json to the desired format.
Besides the string replacement.
I used an answer from Dave R - stack overflow
Use the JSON.stringify(obj, replacer array) replacer method.
var json = JSON.stringify(o, ['__type', 'id', 'parent', 'text', 'type', 'children', 'data', 'li_attr', 'a_attr', 'state', 'class', 'descr', 'display_priority', 'action_area_id', 'action_user_type_id']);
Its a little bit of a pain to list all the keys, but it also acts like a filter, so i only return what i need as well.
And since i put '__type' first, in all the objects and sub objects, this key was listed first after the stringify.
Here's the data I'm trying to deserialize
{
"elements": [
{
"name": "Conference Room 3D",
"code": "room1",
"type": 0,
"bounds": {
"southWestLat": 42.06258564597228,
"southWestLng": -88.05174744187781,
"northEastLat": 42.062638767104781,
"northEastLng": -88.05170306794393
}
},
// ....
]
}
This is quite simple when I'm only expecting a certain kind of data, however I need to be able to put other types of data in that elements array. The type pair is an enumeration which specifies that type of data the object holds. That number then maps to the Class which the object should serialize to.
For Example
0 maps to MapElementConferenceRoom
1 maps to MapElementFocusRoom
etc.
I thought I could just write a custom JsonConverter to read the type key, however you cannot rewind the JsonReader object.
Any suggestion for a solution would be greatly appreicated
dynamic dynJson = JsonConvert.DeserializeObject(json);
foreach (var item in dynJson.elements)
{
if(item.type==0)
{
//Do your specific deserialization here using "item.ToString()"
//For ex,
var x = JsonConvert.DeserializeObject<MapElementConferenceRoom>(item.ToString());
}
}
create a view model that maps directly to the content. then project the specific implementations based on the view model.