JSON.Net getting a dynamic object - c#

I don't think the title of this post explains what the problem is, but I didn't know how to word it.
Basically I have this response from an API of which I have no control over:
"variations":{
"1033308042319364133":{
"id":"1033308042319364133",
"order":null,
"created_at":"2015-07-20 13:45:45",
"updated_at":"2015-07-20 13:47:11",
"title":"Male",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
},
"1033308953984892967":{
"id":"1033308953984892967",
"order":null,
"created_at":"2015-07-20 13:47:34",
"updated_at":"2015-07-20 13:47:34",
"title":"Female",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
},
"1033309404260204585":{
"id":"1033309404260204585",
"order":null,
"created_at":"2015-07-20 13:48:27",
"updated_at":"2015-07-20 13:48:27",
"title":"Male (Junior)",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
},
"1033309540147265579":{
"id":"1033309540147265579",
"order":null,
"created_at":"2015-07-20 13:48:44",
"updated_at":"2015-07-20 13:48:44",
"title":"Female (Junior)",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
}
}
in my c# code I loop through variations like this:
// Get our child variants
var variations = model["variations"];
var IsNull = IsJTokenNull(variations);
var variants = !IsNull ? new List<VariationResponseModel>() : null;
// If we have some variations
if (!IsNull)
{
// Loop through our variations
foreach (var variant in variations)
{
// Add our variant to our list
variants.Add(CreateVariants(variant.First));
}
}
As you can see, I am using variant.First to select the object within the property. My question is, is this the best way to do this? It seems like an awful hack.

This looks like a .net Dictionary more than a list. If VariationResponseModel has the correct properties, you could just do:
var variants = JsonConvert.DeserializeObject<Dictionary<string, Variant>>(variations);
or using the JObject class
var variants = JObject.Parse(variations).ToObject<Dictionary<string, Variant>>();
Both approaches are equivalent, and assume that you got your input as a JSON string. If your input is already a JObject, you can just use:
var variants = variations.ToObject<Dictionary<string, Variant>>()
If you need the variants in a list/enumerable afterwards, just use variants.Values
(JsonConvert / JObject is from the Json.net deserializer)

Related

Replace Json properties with NewtonSoft

No idea where to begin with this, so I don't have any sample code.
I need to change the name of a property in a json document.
var json = (#"{""id"":""12"",
""title"":""My Title"",
""Chunks"":[
{
""id"":""137"",
""title"":""Title"",
""description"":""null"",
""selections"":[
{
""id"":""169"",
""title"":""Choice"",
""sort_order"":""null"",
""questions"":[
]
}
]
}
]
}
}
}");
I need to change the "id" that's got the value of 12 to "document_id" and leave the other ids alone. Are there any C# libraries like NewtonSoft that allow you to change the property rather than the property value. Seems like a common scenario but I haven't seen anything close to what I'm trying to do. I suppose I could convert the json to a string and do a replace, but that doesn't seem very elegant.
An approach using Newtonsoft.Json.Linq.JObject would look something like:
var obj = JObject.Parse(json);
obj["document_id"] = obj["id"]; // create new property called "document_id"
obj.Remove("id"); // remove the "id" property
Console.WriteLine(obj);
Also note that your JSON is not valid. It has two extra } at the end.
Assuming you would want to replace all the keys when there could be more than one node with key as "id" and value "12", you could use Linq to identify Tokens with Key "Id" and Value "12" and then use Add/Remove methods for creating a new node with different name.
For example,
JToken node = JToken.Parse(json);
var jObjectsWithTitle = node
.SelectTokens("$..*")
.OfType<JObject>()
.Where(x => x.Property("id") != null && Convert.ToInt32(x.Property("id").Value) == 12);
foreach(var item in jObjectsWithTitle)
{
item.TryGetValue("id",out var currentValue);
item.Add("document_id",currentValue);
item.Remove("id");
}

Converting json string into list of existing object in C#

I work with an api, that returns a json formatted resultset of a database query.
I have an equivalent object or "model" for the results.
What is the best way to convert the json string into a list of this object?
Of course there are many threads about this, but no one fits my needs properly.
One of the solutions I've found was this:
var jobj = (JObject)JsonConvert.DeserializeObject(json);
var items = jobj.Children()
.Cast<JProperty>()
.Select(j => new
{
ID = j.Name,
Topic = (string)j.Value["Topic_ID"],
Moved = (string)j.Value["Moved_ID"],
Subject = (string)j.Value["subject"],
})
.ToList();
This seems pretty close to what I need. I need to be able to map the keys/values to the appropriate object attributes, which DOES already exist. So maybe you only need to change a few things to make it work for my object?
PS: I'm using Newtonsoft. Any solution for .NET or Newtonsoft or if needed any other library would be great!
I have recently been consuming data from a WebApi and i have been using the following code to convert the json object to an object to work with:
using (var client = new HttpClient())
{
var response = client.GetAsync(apiUri).Result;
// For single objects.
MyObject data = response.Content.ReadAsAsync<MyObject>().Result;
// For an array of objects
IEnumerable<MyObject> data = response.Content.ReadAsAsync<IEnumerable<MyObject>>().Result;
}
Hope this helps.
OK, so you have something like this:
public class MyObject
{
public int ID {get; set;}
public string Topic {get; set;}
public string Subject {get; set;}
}
And you want to instantiate an array of MyObjects with the properties coming from your JSON?
In that case you're just a bout there - you're currently creating a dynamic object with the same properties as MyObject, right? So all you need to do is create an actual MyObject instead:
.Select(j => new **MyObject()**
{
ID = j.Name,
Topic = (string)j.Value["Topic_ID"],
Moved = (string)j.Value["Moved_ID"],
Subject = (string)j.Value["subject"]
})
Note that if your json property names exactly match your C# ones (including case), you can do this as a one-liner with NewtonSoft: http://www.newtonsoft.com/json/help/html/SerializingJSON.htm. But to use that method you'd have to have an intermediate C# class to match your JSON, and then automap (or manually convert) those to MyObjects. Or you'd have to make sure your json and c# properties match exactly. But you're already very close to a quicker (though some would argue less elegant) solution.
Why aren't you deserializing the json into the object type directly? you can do it like this...
var obj = (YourType)JsonConvert.DeserializeObject(
json,
typeof(YourType),
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Auto,
MissingMemberHandling=MissingMemberHandling.Ignore
});
or am I missing something in the question?

Get partial object list from JSON C#

I am calling a RESTful service in C# and the result is similar to this:
{
"blabla":1,
"bbb":false,
"blabla2":{
"aaa":25,
"bbb":25,
"ccc":0
},
"I_want_child_list_from_this":{
"total":15226,
"max_score":1.0,
"I_want_this":[
{
"A":"val1",
"B":"val2",
"C":"val3"
},
{
"A":"val1",
"B":"val2",
"C":"val3"
}
...
]
"more_blabla": "fff"
...
}
I want to get the "I_want_this" part as a list of object or JObject
Is there something like
(JObject)responseString["I_want_child_list_from_this"]["I_want_this"]
more generically:
(JObject)responseString["sub"]["sub_sub"]
I am using Newtonsoft.Json
Thanks!
First off, I would create a class that represents the JSON structure returned from the service call. (http://json2csharp.com/ great utility for auto-generating classes from JSON)
Second, if you are not using Newtonsoft.Json library, I would recommending grabbing that library.
Lastly, use Newtonsoft to deserialize the JSON from the service call into the class you created:
var json = Service.GetJson();
var yourDesiralizedJson = JsonConvert.DeserializeObject<YourJsonToCSharpClass>(json);
var listYouWant = yourDesiralizedJson.IWantChildList.IWantThis;
The below link is appears to be close to the solution as the requester using NewtonSoft.Json as his api to manipulate the object. Appreciate the solutions from other users as well.
look at e.g. here newtonsoft.com/json/help/html/SerializingJSONFragments.htm
The best solution (imo) is to define classes that describe your JSON schema then use DeserializeObject, as suggested by ertdiddy. As a shortcut, you can use DeserializeAnonymousType with incomplete definitions of your schema, taking advantage of JSON's leniency. In your case, this code is working for me:
var testDataFromQuestion = #"
{
""blabla"":1,
""bbb"":false,
""blabla2"":{
""aaa"":25,
""bbb"":25,
""ccc"":0
},
""I_want_child_list_from_this"":{
""total"":15226,
""max_score"":1.0,
""I_want_this"":[
{
""A"":""val1"",
""B"":""val2"",
""C"":""val3""
},
{
""A"":""val1"",
""B"":""val2"",
""C"":""val3""
}
],
""more_blabla"": ""fff""
}";
var anonymousDefinitionOfJson = new {
I_want_child_list_from_this = new {
I_want_this = new Dictionary<string, string>[] {}
}
};
var fullDeserializationOfTestData =
JsonConvert.DeserializeAnonymousType(testDataFromQuestion,
anonymousDefinitionOfJson);
var stuffYouWant = insterestingBits.I_want_child_list_from_this.I_want_this;
Console.WriteLine($"The first thing I want is {stuffYouWant[0]["A"]}");
This outputs the expected value "val1". I'm anonymously defining the minimal classes that get just the data you want, then I'm asking Newtonsoft to parse just enough to populate those classes.

Not able to get dynamic properties with reflection

A dynamic object is generated using a Json deserializing component (Jil) I am using, and I am able to access the properties directly. But I don't know their names in advance, so I am trying to get the names with reflection. I tried doing this:
var props = myDynObj.GetType().GetProperties();
but the page times out. Doesn't give me anything in debugger, just sits there doing nothing, or something and not telling me.
This even happens when I even do this:
var t = myDynObj.GetType();
But when I do this, it works:
var val = myDynObj.MyStaticValue1
Just can't really do anything else with it. Anyonw know why, and how I can get this to work?
Please allow me to note:
Before I get started, if you don't know the members already when you're parsing JSON, you should not be parsing into a dynamic object. The built-in .Net JavaScriptConverter class can parse JSON into a IDictionary<string, object> which would be much better for you.
However, if you still want to use dynamic objects for some reason:
If you want to stick with your current library: I dont know how exactly that class is working, and I'm not saying this is the best solution, but by looking at the source it jumps out to me that you can grab a list of the ObjectMembers keys using reflection.
Type t = typeof(JsonObject)
var fi = t.GetField("ObjectMembers", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
IEnumerable<string> keys = ((Dictionary<string, JsonObject>)fi.GetValue(obj)).Keys;
Edit: Seeing that JsonObject implements IDynamicMetaObjectProvider, the following method mentioned in this question will also work on it:
public static IEnumerable<string> GetMemberNames(object target, bool dynamicOnly = false)
{
var tList = new List<string>();
if (!dynamicOnly)
{
tList.AddRange(target.GetType().GetProperties().Select(it => it.Name));
}
var tTarget = target as IDynamicMetaObjectProvider;
if (tTarget !=null)
{
tList.AddRange(tTarget.GetMetaObject(Expression.Constant(tTarget)).GetDynamicMemberNames());
}else
{
if (ComObjectType != null && ComObjectType.IsInstanceOfType(target) && ComBinder.IsAvailable)
{
tList.AddRange(ComBinder.GetDynamicDataMemberNames(target));
}
}
return tList;
}
If you are open to trying a different JSON converter: try this class here: http://pastie.org/private/vhwfvz0pg06zmjqirtlxa I'm not sure where I found it (I can't take credit) but here is an example of how to use it how you want:
// Create dynamic object from JSON string
dynamic obj = DynamicJsonConverter.CreateSerializer().Deserialize("JSON STRING", typeof(object));
// Get json value
string str = obj.someValue;
// Get list of members
IEnumerable<string> members = (IDictionary<string, object>)obj).Keys
Personally I like using the second one, it is simple and easy to use - and builds off of the built in .Net JSON parser.

json.net IEnumerable

I have the following json file
{"fields":[
{
"status":"active",
"external_id":"title",
"config":{},
"field_id":11848871,
"label":"Title",
"values":[
{
"value":"Test Deliverable"
}
],
"type":"text"
},{
"status":"active",
"external_id":"client-name",
"config":{},
"field_id":12144855,
"label":"Client Name",
"values":[
{
"value":"Chcuk Norris"
}
],
"type":"text"
}}
And I want to select the value of the field that has its external_id = "title" for example, I'm using Json.Net and already parsed the object. How do i do this using lambda or linq on the Json object, I trird something like this
JObject o = JObject.Parse(json);
Title = o["fields"].Select(q => q["extenral_id"].Values[0] == "title");
Which is not event correct in terms of syntax. I'm not very proficient in Lambda or Linq thought its been there for a while. Appreciate the help
Thanks
Yehia
Or you can do this:
string json = "{\"fields\":[{\"status\":\"active\",\"external_id\":\"title\",\"config\":{},\"field_id\":11848871,\"label\":\"Title\",\"values\":[{\"value\":\"Test Deliverable\"}],\"type\":\"text\"},{\"status\":\"active\",\"external_id\":\"client-name\",\"config\":{},\"field_id\":12144855,\"label\":\"Client Name\",\"values\":[{\"value\":\"Chcuk Norris\"}],\"type\":\"text\"}]}";
JObject obj = JObject.Parse(json);
JArray arr = (JArray)obj["fields"];
var externalIds = arr.Children().Select(m=>m["external_id"].Value<string>());
externalIds is a IEnumerable array of string
Or you can chain it together and select the object in one line:
var myVal = JObject.Parse(json)["fields"].Children()
.Where(w => w["external_id"].ToString() == "title")
.First();
From there you can append whatever selector you want ie if you want the external_id value then append ["external_id"].ToString() to the end of the first() selector.
Build classes for your objects first, then parse them so you can access them correctly and its no anonymous type anymore.
For example this classes:
class MyJson {
public List<MyField> fields {get;set;}
}
class MyField {
public string status {get;set;}
public string external_id {get;set;}
// and so on
}
Then use that class for parsing the json (don't know the exact syntax right now) like this:
var o = Json.Parse(json, typeof(MyJson));
And then you can select your data easily with Linq and have intellisense in VS (or similar dev env):
var myData = o.fields.Where(q=>q.external_id=="title");
If you had your JSON converted to objects (basically what Marc suggested), the LINQ query would look something like:
o.fields.Single(q => q.external_id == "title")
But if you don't want to do that, you have to access the values by string keys. If you don't want to convert the type of the value, you can simply use indexing (["key"]). But if you want to convert the type, you can use Value<Type>("key"). Putting it together, the whole query might be:
o["fields"].Single(q => q.Value<string>("external_id") == "title")

Categories

Resources