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.
Related
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;
}
I am trying to get around that C# prefers to have classes generated (I know they are easy to generate, but currently my format and parameters are changing a lot due to development in both client and server end).
Example of what I most often find when I try to find out to deserialize is that you first have to know the exact structure - then build a class - and then you can refer to it later on (it's fine, but it's just not what I would like to do):
Json format 1:
[{"FirstName":"Bob","LastName":"Johnson"},{"FirstName":"Dan","LastName":"Rather"}]
public class People
{
public string FirstName { get; set; }
public string LastName { get; set;}
}
public List<People> peopleList;
. . . // (same as first example)
//Change the deserialize code to type <List<Class>>
peopleList = deserial.Deserialize<List<People>>(response);
That of course is easy as long as the reply doesn't change format, if for example the reply changes to a nested field :
Json format 2:
[{"FirstName":"Bob","LastName":"Johnson"},{"data":{"nestedfield1"
:"ewr"} }]
I would of course have to change the class to represent that, but at the moment we are moving back and forth in formats and I would somehow like if there was a way where I could try to access json elements directly in the string?
For example, like I can do in Python:
mystring1 = reply ["firstName"] mystring2 = reply ["data"]["nestedfield1"]
Is there any way to achieve this in C#? It would speed up development rapidly if there was a way of accessing it without first referencing the output in the code to then once again reference the class variable that was created when referencing it.
And note it's for rapid development, not necessarily for the final implementation where I can see advantages by doing the class approach.
Another way of asking was maybe can it serialize taking any format (as long as its JSON) and dynamically build up a struct where I can access it with named keys and not as class variables?
to deserialize json without using classes you can use using Newtonsoft.Json
here's the code:
using System;
using Newtonsoft.Json;
using System.Text;
public class Program
{
public static void Main()
{
var myJSONString = "[{\"FirstName\":\"Bob\",\"LastName\":\"Johnson\"},{\"FirstName\":\"Dan\",\"LastName\":\"Rather\"}]";
dynamic obj = JsonConvert.DeserializeObject<dynamic>(myJSONString);
Console.WriteLine(obj[0].FirstName);
}
}
The obj will perform the same way you use when generating classes,
it can take any json string and deserialize into dynamic object regardless of structure of the json. Keep in mind that you won't get VS intellisense support.
UPDATE
Here's fiddle:
https://dotnetfiddle.net/xeLDpK
I have a json String(array) like this:
[{"user":{"name":"abc","gender":"Male","birthday":"1987-8-8"}},
{"user":{"name":"xyz","gender":"Female","birthday":"1987-7-7"}}]
and want to parse it to json object using .net4.0 framework only, and i cannot use DataContractJsonSerializer as it requires class and i am receiving dynamic data over web services within 1 minute which keep changing and it is in Name-value format,i tried using JavaScriptSerializer but i am unable to add system.web.extension in my vs2010 project .net4.0 supported framework,and i don't want to use any third party library,actually i am New-bie in wpf,so please it would be great help,thanks in advance!
Well there are two main issues I can see here, and one additional.
1) If you do not have particular class that you could deserialize JSON to, then you have to rely on some "dictionary-like" structure (e.g. dynamic or JToken)to be able to access all fields. However data you presented seems to be structured, so maybe consider creating POCO to get advantage of strongly-typed structure. Both can be easily achieved using ready-to-use libraries.
2) You say you don't want to use any third party library, but actually there is nothing wrong with it. Actually you should be doing so to avoid reinventing the wheel as Tewr mentioned. It's perfectly fine to use in fact industry-standard library such as Newtonsoft Json so you can avoid tons of bugs, unnecessary work and future troubles. If your point is to learn by writing JSON (de)serializer it's perfectly fine, but I'd recommend against using it in production code.
Side note: you mentioned you receive data over web-service, and it seems you receive simply JSON array (as top-level object). It's considered as security hole. More information may be found here:
https://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/
What are "top level JSON arrays" and why are they a security risk?
EDIT 2017-11-05:
Ok, so you should create classes representing response from your web service (you can use feature of VS called Edit > Paste Special > Paste JSON As Classes):
public class Response
{
public User[] users { get; set; }
}
public class User
{
public string Name { get; set; }
public string gender { get; set; }
public string birthday { get; set; }
}
Now using Nuget install package Newtonsoft.Json and using following code you'll deserialize JSON response to .NET classes:
string responseText = "";//Get it from web service
var response = JsonConvert.DeserializeObject<Response>(responseText);
Hope this help!
This question already has answers here:
How do I turn a C# object into a JSON string in .NET?
(15 answers)
Closed 6 years ago.
I'm working on a point system for my twitch chat bot in C#. I need to save a list of users with their amount of points and hours to a local .txt file like this:
users : ???
username : ???
nick : string
points : int
hours : int
username : ???
nick : string
points : int
hours : int
username : ???
nick : string
points : int
hours : int
I'm trying to create a .NET Object to serialize to a JSON string and write this to my .txt file but I'm stuck here.
I figure users needs to be an Array of some sort but what do I do with username? I don't think JSON supports custom types?
Thanks for your time,
X3ntr
First we need to create a model. This model needs to match the structure of the JSON. There are a couple of ways to create this model.
Probably the best and safest way is to write it manualy. If you are using vs2015 you can also copy the json and paste it as class.
You can find this option here:
Another option is to use a website like http://json2csharp.com/ here you can paste the JSON and this will also generate classes for your JSON. Keep in mind that these generator are not 100% accurate so you might have to change some properties your self.
Ones we got the model we can use a lib like JSON.net to Deserialize our JSON. On the website is also some extra documentation on how to use JSON.net
var userList = JsonConvert.DeserializeObject<List<UserModel>>(users); //Users being the json as text.
Remember that if you miss a property in you model this will not always throw an error. So make sure that all properties got serialize correctly.
Serializing is as simple as Deserializing.
string json = JsonConvert.SerializeObject(model);
File.WriteAllText("C:\json.txt",json);
Optional is adding an encoding when writing the json.
File.WriteAllText("C:\json.txt",json,Encoding.UTF8);
I'll take a shot at it.
First up we'll need a model for our user:
public class User
{
public Guid Id { get; set; }
public string Username { get; set; }
public string NickName { get; set; }
public int Points { get ;set; }
public int Hours { get; set; }
}
Then in your main method, or wherever you deal with your users:
List<User> users = new List<User>();
Notice that I've added an Id property. Even though your usernames might very well be unique, it's always good practice to have some sort of property whose entire job is to just be the Id. This property should never change throughout the lifetime of the user. Where username might change one day, the Id will always stay the same.
Anyways, now to turn your list into Json:
string myJsonString = JsonConvert.SerializeObject(users, Formatting.Indented);
Et voila! Your list of users is now in a tidy Json string. The above line of code is from JSON.NET, you can get it as a Nuget package. The full qualification is Newtonsoft.Json.JsonConvert. You can pretty much trust JSON.NET to handle almost anything you throw at it, especially for a simple User class like you're going to be throwing at it.
Hope this helps get you started.
I have a Generic Envelope class that i use as the common return object for the WebAPI as follows:
public class ApiEnvelope<T>
{
public bool Success { get; set; }
public Error Error { get; set; }
public Data<T> Data { get; set; }
}
Then I construct a HttpResponseMessage using:
Request.CreateResponse<ApiEnvelope<whatever>>(HttpStatusCude.OK, model);
The problem i have is that i would like the xml to be somewhat standard however the root name of the xml being returned is not standard and is coming through as ApiEnvelopeOfwhatever.
My question is how can i get the root name to be ApiEnvelope regardless of the type?
With generic class you got no chance, remove generic specification and set Data propert type to object.
I had a similar question and I got a decent answer, (I know this is old but it was a good answer): How to resolve Swashbuckle/Swagger -UI model naming issue for generics?
Now this is only part of the solution for your question, so you should look at Github repo: MakeGenericAgain. Use that to "regeneric" the resultant generated code, (big heads up: if you use this on the entire code and not just names of types, you will have a mess if you have properties name things like "NumberOfUnits" because that becomes "Number").
Sidenote:
If you want to "level up" your skills here, then use Rolsyn's SyntaxWalker to apply the renaming, and at the same time "cleanup" duplicated classes, as many design their REST-APIs with few shared "models" so a User and a Company might hace identical "Address" -properties based on identically shaped classes but it they are defined twice your NSwag -generated code will have Address and Address2, however using Roslyn, you can identify these ande rewrite the code to give a "perfect result".