Get a specific part of my JSON data in C# - c#

I have this JSON:
{
"response":
{
"data":
[
{
"start":1,
"subjects":["A"]
},
{
"start":3,
"subjects":["B"]
},
{
"start":2,
"subjects":["C"]
}
]
}
}
And I want to get only the "subject" data from the object with it's "start" value to be the smallest one that is greater than 1.3, which in this case would be C. Would anybody happen to know how such a thing can be achieved using C#?

I want to extend a bit on the other answers and shed more light into the subject.
A JSON -- JavaScript Object Notation - is just a way to move data "on a wire". Inside .NET, you shouldn't really consider your object to be a JSON, although you may colloquially refer to a data structure as such.
Having said that, what is a JSON "inside" .NET? It's your call. You can, for instance treat it as a string, but you will have a hard time doing this operation of finding a specific node based on certain parameters/rules.
Since a JSON is a tree-like structure, you could build your on data structure or use the many available on the web. This is great if you are learning the workings of the language and programming in general, bad if you are doing this professionally because you will probably be reinventing the wheel. And parsing the JSON is not a easy thing to do (again, good exercise).
So, the most time-effective way of doing? You have two options:
Use a dynamic object to represent your JSON data. A dynamic is a "extension" to .NET (actually, an extension to the CLR, that is called DLR) which lets you create objects that doesn't have classes (they can be considered to be "untyped", or, better, to use duck typing).
Use a typed structure that you defined to hold your data. This is the canonical, object-oriented, .NET way of doing it, but there's a trade-off in declaring classes and typing everything, which is costly in terms of time. The payoff is that you get better intellisense, performance (DLR objects are slower than traditional objects) and more safe code.
To go with the first approach, you can refer to #YouneS answer. You need to add a dependency to your project, Newtonsoft.Json (a nuget), and call deserialize to convert the JSON string to a dynamic object. As you can see from his answer, you can access properties in this object as you would access then on a JavaScript language. But you'll also realize that you have no intellisense and things such as myObj.unexistentField = "asd" will be allowed. That is the nature of dynamic typed objects.
The second approach is to declare all types. Again, this is time consuming and on many cases you'll prefer not to do it. Refer to Microsoft Docs to get more insight.
You should first create your data contracts, as below (forgive me for any typos, I'm not compiling the code).
[DataContract]
class DataItem
{
[DataMember]
public string Start { get; set; }
[DataMember]
public string[] Subjects { get; set; }
}
[DataContract]
class ResponseItem
{
[DataMember]
public DateItem[] Data { get; set; }
}
[DataContract]
class ResponseContract
{
[DataMember]
public ResponseItem Response { get; set; }
}
Once you have all those data structures declared, deserialize your json to it:
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
var deserializer = new DataContractJsonSerializer(typeof(ResponseContract));
return (T)deserializer.ReadObject(ms);
}
The code above may seem a bit complicated, but follow a bit of .NET / BCL standards. The DataContractJsonSerializer work only with streams, so you need to open a stream that contains your string. So you create a memory stream with all the bytes from the json string.
You can also use Newtonsoft to do that, which is much simpler but, of course, still requires that extra dependency:
DataContract contract = JsonConvert.DeserializeObject<DataContract>(output);
If you use this approach you don't need the annotations (all those DataMember and DataContract) on your classes, making code a bit more clean. I very much prefer using this approach than DataContractJsonSerializer, but it's your call.
I've talked a lot about serializing and deserializing objects, but your question was, "How do I find a certain node?". All the discussion above was just a prerequisite.
There are, again and as usual, a few ways of achieving what you want:
#YouneS answer. It's very straightforward and achieves what you are looking for.
Use the second approach above, and then use your typed object to get what you want. For instance:
var contract = JsonConvert.DeserializeObject<DataContract>(output);
var query = from dataItem in contract.Response.Data
where dataItem.Start > 1.3
order by dataItem.Start;
var item = query.FirstOrNull();
Which will return the first item which, since it's ordered, should be the smallest. Remember to test the result for null.
You can use a feature from Newtonsoft that enables to directly find the node you want. Refer to the documentation. A warning, it's a bit advanced and probably overkill for simple cases.

You can make it work with something like the following code :
// Dynamic object that will hold your Deserialized json string
dynamic myObj = JsonConvert.DeserializeObject<dynamic>(YOUR-JSON-STRING);
// Will hold the value you are looking for
string[] mySubjectValue = "";
// Looking for your subject value
foreach(var o in myObj.response.data) {
if(o.start > 1.3)
mySubjectValue = o.subjects;
}

Related

Parsing (many) JSON different objects to C# classes. Is strongly typed better?

I have been working on a client - server project. The server side implemented on PHP. The client implemented on C#. The websocket is used for connection between them.
So, here is the problem. Client will make a request. Json is in use for sending objects and validating against the schema. The request MUST HAVE it's name and MAY contain args. Args are like associative array (key => value).
Server will give a response. Response MAY contain args, objects, array of objects. For example, client sends a request like:
{
"name": "AuthenticationRequest",
"username": "root",
"password": "password",
"etc": "etc"
}
For this, server will reply with an AuthSuccess or AuthFailed response like:
{
"name": "AuthFailed",
"args": [
{
"reason": "Reason text"
}]
}
If response is AuthSuccess, client will send a requst of who is online. Server must send an array of users.
And so on. So the problem is, how to store those responses on a client side. I mean, the way of creating a new object for each response type is insane. They will be hundreds of request types, and each of them requires it's own response. And any changing in structure of request will be very very hard...
Need some kind of pattern or trick. I know it's kind of a noob way... But if anyone has a better idea of implementing request/response structure, please tell it.
Best regards!
I'd definitely go with a new class for each request type. Yes, you may need to write a lot of code but it'll be safer. The point (to me) is who will write this code?. Let's read this answer to the end (or directly jump to last suggested option).
In these examples I'll use Dictionary<string, string> for generic objects but you may/should use a proper class (which doesn't expose dictionary), arrays, generic enumerations or whatever you'll feel comfortable with.
1. (Almost) Strongly Typed Classes
Each request has its own strongly typed class, for example:
abstract class Request {
protected Request(string name) {
Name = name;
}
public string Name { get; private set; }
public Dictionary<string, string> Args { get; set; }
}
sealed class AuthenticationRequest : Request
{
public AuthenticationRequest() : base("AuthenticationRequest") {
}
public string UserName { get; set; }
public string Password { get; set; }
}
Note that you may switch to a full typed approach also dropping Dictionary for Args in favor of typed classes.
Pros
What you saw as a drawback (changes are harder) is IMO a big benefit. If you change anything server-side then your request will fail because properties won't match. No subtle bugs where fields are left uninitialized because of typos in strings.
It's strongly typed then your C# code is easier to maintain, you have compile-time checks (both for names and types).
Refactoring is easier because IDE can do it for you, no need to blind search and replace raw strings.
It's easy to implement complex types, your arguments aren't limited to plain string (it may not be an issue now but you may require it later).
Cons
You have more code to write at very beginning (however class hierarchy will also help you to spot out dependencies and similarities).
2. Mixed Approach
Common parameters (name and arguments) are typed but everything else is stored in a dictionary.
sealed class Request {
public string Name { get; set; }
public Dictionary<string, string> Args { get; set; }
public Dictionary<string, string> Properties { get; set; }
}
With a mixed approach you keep some benefits of typed classes but you don't have to define each request type.
Pros
It's faster to implement than a almost/full typed approach.
You have some degree of compile-time checks.
You can reuse all code (I'd suppose your Request class will be also reused for Response class and if you move your helper methods - such as GetInt32() - to a base class then you'll write code once).
Cons
It's unsafe, wrong types (for example you retrieve an integer from a string property) aren't detected until error actually occurs at run-time.
Changes won't break compilation: if you change property name then you have to manually search each place you used that property. Automatic refactoring won't work. This may cause bugs pretty hard to detect.
Your code will be polluted with string constants (yes, you may define const string fields) and casts.
It's hard to use complex types for your arguments and you're limited to string values (or types that can be easily serialized/converted to a plain string).
3. Dynamic
Dynamic objects let you define an object and access it properties/methods as a typed class but they will be actually dynamically resolved at run-time.
dynamic request = new ExpandoObject();
request.Name = "AuthenticationRequest";
request.UserName = "test";
Note that you may also have this easy to use syntax:
dynamic request = new {
Name = "AuthenticationRequest",
UserName = "test"
};
Pros
If you add a property to your schema you don't need to update your code if you don't use it.
It's little bit more safe than an untyped approach. For example if request is filled with:
request.UserName = "test";
If you wrongly write this:
Console.WriteLine(request.User);
You will have a run-time error and you still have some basic type checking/conversion.
Code is little bit more readable than completely untyped approach.
It's easy and possible to have complex types.
Cons
Even if code is little bit more readable than completely untyped approach you still can't use refactoring features of your IDE and you almost don't have compile-time checks.
If you change a property name or structure in your schema and you forget to update your code (somewhere) you will have an error only at run-time when it'll happen you use it.
4. Auto-generated Strongly Typed Classes
Last but best...so far we did forget an important thing: JSON has schema with which it can be validatd (see json-schema.org).
How it can be useful? Your fully typed classes can be generated from that schema, let's take a look to JSON schema to POCO. If you don't have/don't want to use a schema you still can generate classes from JSON examples: take a look to JSON C# Class Generator project.
Just create one example (or schema) for each request/response and use a custom code generator/build task to build C# classes from that, something like this (see also MSDN about custom build tools):
Cvent.SchemaToPoco.Console.exe -s %(FullPath) -o .\%(Filename).cs -n CsClient.Model
Pro
All the pros of above solutions.
Cons
Nothing I can think about...
Why is it a problem to create a class for each kind of Request / Response? If you have hundreds of different kinds of Requests and Responses, you might want to try and categorize them better.
I would argue there are common patterns across your requests or responses. Eg. a FailureResponse might always contain some status information and maybe an UserData-object (which could be anything depending on the use-case). This can be applied to other categories likewise (eg. SuccessResponse).
dynamic is a new static type that acts like a placeholder for a type not known until runtime. Once the dynamic object is declared, it is possible to call operations, get and set properties on it, even pass the dynamic instance pretty much as if it were any normal type. dynamic gives us a lot of rope to hang themselves with. When dealing with objects whose types can be known at compile time, you should avoid the dynamic keyword at all costs
You can read more about Dynamic

C# JSON.NET How can I create generic telegram?

I am building a C# (.NET 4.5) generic "telegram" - for lack of a better word - that communicates between a plc and a regular pc using tcp and JSON, especially JSON.NET. I have a tcp server set up and working, and I can create Json strings out of objects, which can then be passed on. So I am left with defining a standard way to pass information, commands and events back and forth. What I am now struggling with is how to easily format the "payload". I have a JsonTelegram class with a dynamic variable called "payload" - more or less this:
private dynamic _payload;
public dynamic payload
{
get
{
return _payload;
}
set
{
_payload = value;
updateContents();
}
}
So if I update this variable like this:
myTelegram.payload = rampTime;
I would like to see the final JSON be this:
{
"purpose": "Update this variable",
"payload": {
"rampTime": 2000
},
"timeStamp": "2000-01-01T00:00:00.000-00:00",
"returnID": "2000-01-01T00:00:00.000-00:00"
}
It is the payload part that I am really struggling with, because that code there will end up looking like this:
{
"purpose": "Update this variable",
"payload": 2000,
"timeStamp": "2000-01-01T00:00:00.000-00:00",
"returnID": "2000-01-01T00:00:00.000-00:00"
}
when updateContents() uses this:
... Newtonsoft.Json.JsonConvert.SerializeObject(_payload) ...
Do you see how the word "ramp" gets replaced with "payload"? I know I could just make a method and pass both the object and the name of the object - this would definitely work. But I would like to get trickier than that, just because it should be possible, and also because down the road I can see some other reasons that this design may work better. I want the code to simply know the name of the variable that called it and use that. I have seen many suggestions using some stuff I barely understand, but when I try to adapt it, it seems to get hung up on one issue or another. So I thought I would ask a fresh question, because surely many people want to do the same thing with JSON and the new dynamics?
StackOverflow has information on attributes and dictionaries, reflection, something to do with t, expressions, and so on. For instance, this question: How do you get a variable's name as it was physically typed in its declaration? and this Finding the variable name passed to a function
I don't mind making the class code as messy and hacky as all get out, but I want the calling code to be as clean as "myTelegram.payload = rampTime;"
I'm sorry that I can't wade through all the suggestions well enough - I spend most of my time writing plc code, and just now have a plc that one side does C#.
Also, if there is simply a more elegant way to do things that is totally different, I am eager to hear it.
Thanks!
It sounds like you're looking for an ExpandoObject. With an ExpandoObject, your telegram looks something like:
class Telegram
{
private dynamic _payload = new ExpandoObject();
public dynamic payload
{
get
{
return _payload;
}
}
public string ToJson()
{
...
}
}
And in your code:
var telegram = new Telegram();
telegram.payload.rampTime = 2000;
Console.WriteLine(telegram.ToJson());

C# Parsing json into generic collection

Parsing Google Plus JSON objects
Using C# and Newtonsoft.Json library how one can parse following json code?
[["tsg.lac",
[[["3a4a7e8e0b3d5d66"],["Friends",null,"Your real friends, the ones you feel comfortable sharing private details with.",null,null,null,null,null,null,2,2,null,"00000000",1,1,1]]
,[["5947b6d78a8231f3"],["Family",null,"Your close and extended family, with as many or as few in-laws as you want.",null,null,null,null,null,null,2,2,null,"00000001",2,1,1]]
,[["22d0e3ec8c38fa24"],["Acquaintances",null,"A good place to stick people you've met but aren't particularly close to.",null,null,null,null,null,null,2,2,null,"00000002",5,1,1]]
,[["1adf9b0b0987c2ad"],["Following",null,"People you don't know personally, but whose posts you find interesting.",null,null,null,null,null,null,2,2,null,"00000003",6,1,1]]
,[["15"],["Blocked",null,null,null,null,null,null,null,null,2,1,null,"z9",null,1,1]]]
,[]
]
]
Basically how do you parse Json if you do not know the original structure?
Is it possible to parse it into generic key/value collection?
You can parse it like
JArray jobj = (JArray)Newtonsoft.Json.JsonConvert.DeserializeObject(jStr);
foreach (var x in jobj[0][1])
{
Console.WriteLine(x[0][0] + " " + x[1][2]);
}
and the output will be
3a4a7e8e0b3d5d66 Your real friends, the ones you feel comfortable sharing private details with.
5947b6d78a8231f3 Your close and extended family, with as many or as few in-laws as you want.
22d0e3ec8c38fa24 A good place to stick people you've met but aren't particularly close to.
1adf9b0b0987c2ad People you don't know personally, but whose posts you find interesting.
PS: JsonView is a very good tool to help you
I think the answer depends on what you want to do with the data. If you are looking to extract specific pieces of information, I would build a class that contains the elements that you are looking to use and has placeholders for the rest, then deserialize into that class.
You can verify that the class is constructed correctly by first serializing a sample class and verifying that it produces the same output as what you are trying to parse.
You could use
JsonConvert.DeserializeObject<ElementType>("your json string here");
where the ElementType must be defined for your json data, could be something like:
[Serializable]
public class ElementType
{
public string ConstituentID { set; get; }
public string Email { set; get; }
}
(this one i pulled from somewhere and it does not correspond to you JSON structure)
Ie. it must capture your JSON structure.

From object to proper types: Is this the/a "right" way to work with this non-generified, object-returning API?

One particular aspect of some code I've written is causing me minor headaches, I can't pinpoint the reason - all the type checking and casting is making me feel uneasy. The code works as it is right now. I'd like to know wether or not there's a better way to handle the type-specific aspects of the code.
I'm using a non-generified, object-returning JSON parser which makes me go through various incantations in my generified code.
The signature of the parse method is public static object JsonDecode(string json) The runtime type of the object it returns can be ArrayList, Hashtable, double or string. I'm calling the JsonDecode method on a Twitter Search response, which returns the result tweets as a top level object of the form:
{"results":[
{"text":"#twitterapi http:\/\/tinyurl.com\/ctrefg",
"to_user_id":396524,
"to_user":"TwitterAPI",
"from_user":"jkoum",
"metadata":
{
"result_type":"popular",
"recent_retweets": 109
}, ... MORE-DATA ...}
The context in which I'm using the JsonDecode(string json) method is
private IList<Tweet> searchResult = new List<Tweet>();
var jsonDecoded = JSON.JsonDecode(responseString);
IList rawTweets =
(IList)((Hashtable)jsonDecoded)["results"];
foreach (var rawTweet in rawTweets)
{
searchResult.Add(new Tweet((Hashtable) rawTweet));
}
The Tweet class does its own type checking and casting
class Tweet : DynamicObject
{
private IDictionary<string, string> stringValues =
new Dictionary<string, string>();
private IDictionary<string, double> numberValues =
new Dictionary<string, double>();
public Tweet(Hashtable rawTweet)
{
FlattenJSON(rawTweet);
}
//flatten input and assign to correct map/dictionary based on JSON value type
private void FlattenJSON(Hashtable table)
{
foreach (DictionaryEntry entry in table)
{
//this code is not handling the case, that the Tweet contains a JSON array
//not necessary as of now: this code is intended for demo purposes in a talk
//I'm giving on Friday 2010-06-25
if (entry.Value is String)
stringValues.Add((string)entry.Key, (string)entry.Value);
else if (entry.Value is Double)
numberValues.Add((string)entry.Key, (double)entry.Value);
else if (entry.Value is Hashtable)
FlattenJSON((Hashtable)entry.Value);
}
}
...
}
Am I handling the type checks in the FlattenJSON method correctly? What about the casts in the code snippet building the IList and constructing the searchResult IList<Tweet>? Would you have written the code in a different way?
As a side note, the complete code is available via http://github.com/codesurgeon/pop-tweets The code is intended for a demo in a talk that I'll be giving on selected .NET features. The Tweet class is a DynamicObject and it overrides TryGetMember, see full listing on github.
Thank you ;)
P.S.: [FYI] This is a more specific version of my previous post, requesting a general code review https://stackoverflow.com/questions/3113293/how-to-be-a-good-c-citizen-review-requested-for-c-4-0-dynamic-sample-code
A few things stand out to me:
First, you should so some argument validation. Check to see if "table" is null before you start using it. Otherwise, you will get an unhandled NullReferenceException and it will confuse your consumer.
Next, does this actually work? The "is" keyword (I thought) only worked with reference types, and double is a value type. I would assume that this wouldn't work and you'd need to instead do a double.TryParse().
Lastly, there is a lot of casting on-the-fly. When you are interacting with a 3rd-party API, I would argue that you should have an interface where you convert from "their weird stuff" to "your clean stuff". So even if the API is messy and difficult, clean it up and present it to your consumer in the proper way. Don't propogate the bad design. In other words, as a consuming developer, I would want some obvious and clean data structures to work with. Like: foreach(Tweet tweet in Twitter.GetTweets()) or something. I don't care that you happen to use json right now. That implementation should be be invisible to me.
Hope that helps...
I would not do it like that.
First of all, your tweet class is not a real object, it's a data container. You could just continue to work with the jsonDecoded variable, since your tweet class doesn't add any functionality or abstraction (other than abstracting away the JSON decoder).
How I would do it:
Create POCOs which holds the information: Tweet and a Metadata class.
Create a serializer which takes the JSON string and returns the Tweet class
By dividing it into two steps and also creating real classes you will have it much easier in the future. Please read about Single Responsibility.

What is a good design when trying to build objects from a list of key value pairs?

So if I have a method of parsing a text file and returning a list of a list of key value pairs, and want to create objects from the kvps returned (each list of kvps represents a different object), what would be the best method?
The first method that pops into mind is pretty simple, just keep a list of keywords:
private const string NAME = "name";
private const string PREFIX = "prefix";
and check against the keys I get for the constants I want, defined above. This is a fairly core piece of the project I'm working on though, so I want to do it well; does anyone have any more robust suggestions (not saying there's anything inherently un-robust about the above method - I'm just asking around)?
Edit:
More details have been asked for. I'm working on a little game in my spare time, and I am building up the game world with configuration files. There are four - one defines all creatures, another defines all areas (and their locations in a map), another all objects, and a final one defines various configuration options and things that don't fit else where. With the first three configuration files, I will be creating objects based on the content of the files - it will be quite text-heavy, so there will be a lot of strings, things like names, plurals, prefixes - that sort of thing. The configuration values are all like so:
-
key: value
key: value
-
key: value
key: value
-
Where the '-' line denotes a new section/object.
Take a deep look at the XmlSerializer. Even if you are constrained to not use XML on-disk, you might want to copy some of its features. This could then look like this:
public class DataObject {
[Column("name")]
public string Name { get; set; }
[Column("prefix")]
public string Prefix { get; set; }
}
Be careful though to include some kind of format version in your files, or you will be in hell's kitchen come the next format change.
Making a lot of unwarranted assumptions, I think that the best approach would be to create a Factory that will receive the list of key value pairs and return the proper object or throw an exception if it's invalid (or create a dummy object, or whatever is better in the particular case).
private class Factory {
public static IConfigurationObject Factory(List<string> keyValuePair) {
switch (keyValuePair[0]) {
case "x":
return new x(keyValuePair[1]);
break;
/* etc. */
default:
throw new ArgumentException("Wrong parameter in the file");
}
}
}
The strongest assumption here is that all your objects can be treated partly like the same (ie, they implement the same interface (IConfigurationObject in the example) or belong to the same inheritance tree).
If they don't, then it depends on your program flow and what are you doing with them. But nonetheless, they should :)
EDIT: Given your explanation, you could have one Factory per file type, the switch in it would be the authoritative source on the allowed types per file type and they probably share something in common. Reflection is possible, but it's riskier because it's less obvious and self documenting than this one.
What do you need object for? The way you describe it, you'll use them as some kind (of key-wise) restricted map anyway. If you do not need some kind of inheritance, I'd simply wrap a map-like structure into a object like this:
[java-inspired pseudo-code:]
class RestrictedKVDataStore {
const ALLOWED_KEYS = new Collection('name', 'prefix');
Map data = new Map();
void put(String key, Object value) {
if (ALLOWED_KEYS.contains(key))
data.put(key, value)
}
Object get(String key) {
return data.get(key);
}
}
You could create an interface that matched the column names, and then use the Reflection.Emit API to create a type at runtime that gave access to the data in the fields.
EDIT:
Scratch that, this still applies, but I think what your doing is reading a configuration file and parsing it into this:
List<List<KeyValuePair<String,String>>> itemConfig =
new List<List<KeyValuePair<String,String>>>();
In this case, we can still use a reflection factory to instantiate the objects, I'd just pass in the nested inner list to it, instead of passing each individual key/value pair.
OLD POST:
Here is a clever little way to do this using reflection:
The basic idea:
Use a common base class for each Object class.
Put all of these classes in their own assembly.
Put this factory in that assembly too.
Pass in the KeyValuePair that you read from your config, and in return it finds the class that matches KV.Key and instantiates it with KV.Value
public class KeyValueToObjectFactory
{
private Dictionary _kvTypes = new Dictionary();
public KeyValueToObjectFactory()
{
// Preload the Types into a dictionary so we can look them up later
// Obviously, you want to reuse the factory to minimize overhead, so don't
// do something stupid like instantiate a new factory in a loop.
foreach (Type type in typeof(KeyValueToObjectFactory).Assembly.GetTypes())
{
if (type.IsSubclassOf(typeof(KVObjectBase)))
{
_kvTypes[type.Name.ToLower()] = type;
}
}
}
public KVObjectBase CreateObjectFromKV(KeyValuePair kv)
{
if (kv != null)
{
string kvName = kv.Key;
// If the Type information is in our Dictionary, instantiate a new instance of that class.
Type kvType;
if (_kvTypes.TryGetValue(kvName, out kvType))
{
return (KVObjectBase)Activator.CreateInstance(kvType, kv.Value);
}
else
{
throw new ArgumentException("Unrecognized KV Pair");
}
}
else
{
return null;
}
}
}
#David:
I already have the parser (and most of these will be hand written, so I decided against XML). But that looks like I really nice way of doing it; I'll have to check it out. Excellent point about versioning too.
#Argelbargel:
That looks good too. :')
...This is a fairly core piece of the
project I'm working on though...
Is it really?
It's tempting to just abstract it and provide a basic implementation with the intention of refactoring later on.
Then you can get on with what matters: the game.
Just a thought
<bb />
Is it really?
Yes; I have thought this out. Far be it from me to do more work than neccessary. :')

Categories