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!
Extending on from this question, I'm trying to pass a complex object containing a collection of complex objects to an ASP.NET Web API controller action method, but I'm having trouble finding the correct format to use for my input object in the request. Continuing the example from Christopher Johnson's question (and removing some fields for simplicty), if I change his PhoneRequest object to contain a collection of phone numbers...
public class PhoneRequest
{
public string[] PhoneNumbers { get; set; }
public string State { get; set; }
}
...and I either pass the parameter as a URL encoded query string:
/api/phonenumber?id[0][State]=UT&id[0][PhoneNumbers][0]=555-1234567
...or POST it as a html form encoded (Content-Type: application/x-www-form-urlencoded) request body:
[0][State]=UT&[0][PhoneNumbers][0]=555-1234567
...then everything works great. But If I change PhoneNumbers from a collection of strings to a collection of a new PhoneNumber type...
public class PhoneRequest
{
public PhoneNumber[] PhoneNumbers { get; set; }
public string State { get; set; }
}
public class PhoneNumber
{
string AreaCode { get; set; }
string Number { get; set; }
}
...and I pass the object in what appears to me to be the logical way, given the previous result...
id[0][State]=UT&id[0][PhoneNumbers][0][AreaCode]=555&id[0][PhoneNumbers][0][Number]=1234567
...or again as a html form post body...
[0][State]=UT&[0][PhoneNumbers][0][AreaCode]=555&[0][PhoneNumbers][0][Number]=1234567
...then it still makes an attempt to bind it, and gets into my action method, but the model only contains State, and the phone number is this weird ComplexUriAndFormObject thing. Here's a copy-paste from my debugger Watch:
phoneRequest {ComplexUriAndFormObject.Models.PhoneRequest[1]}
[0] {ComplexUriAndFormObject.Models.PhoneRequest}
PhoneNumbers {ComplexUriAndFormObject.Models.PhoneNumber[1]}
[0] {ComplexUriAndFormObject.Models.PhoneNumber}
AreaCode null
Number null
State "UT"
Is there some way to specify this object correctly using this format? Or have I exceeded the limit of what ASP.NET Web API's built in model binders are able to do?
Note: Please don't say "just use POST" or "just use JSON/XML/Whatever as your Content-Type"... If I was able to do that, I would.
Until now, no built-in Web API model binders including derived FromUri and FromBody attributes support passing a complex object that contains any property of non-primitive class types (excluding the System.String) with query strings. I had the similar issues and have created a unique and advanced custom model binder, the FieldValueModelBinder class, to work on a target object hierarchy having generic list or array collections. I can use the pure query string type of source data without imbedding any JSON or XML structure into it. The model binder can be used as easy as the FromUri and FromBody attributes. It also works effectively for transferring query string data in both URI and request body.
Please read my article and download source code I have just posted using this link. You can also run the test app from the download source for your input string, model, and results. I hope that this is the right solution you need.
I'm forced to use GET requests to pass complex objects to my application.
How can I deserialize a querystring like this:
?people[andy]=12&people[bob]=43&people[charlie]=53&items=89&items=123&x=zulu
into a custom object like this?
public class myClass {
public Dictionary<string, int> people { get; set; }
public int[] items { get; set; }
public string x { get; set; }
}
Is there a better (more sophisticated) way to do this besides splitting it by & and looping through the results to manually set each value?
Any pointers / guidance would be greatly appreciated.
If you have control over the sending side of the application, I strongly suggest you use a different encoding method to make parsing easier. I would just JSON encode the entire object, and then URIencode the JSON if it must be in the query_string.
There are often fairly small (on the order of 2K characters) limits to the size of URIs including the query_string. If you are forced to use HTTP, depending on your use case and whether you have control over this, POST may be preferable.
See this question for some methods of deserializing JSON:
C# deserialize dynamic JSON
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.