parse string to json object in wpf? - c#

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!

Related

Blazor C# .Net 6.0 oData $metadata: Generated Proxy Vs typed HttpClient

I have a Blazor Server .net 6.0 app that I wish to consume a number of API's in.
One SOAP API is setup using the Service Reference wizard and has built the proxy class and models and I can use this without issue.
I have two more that are oData based, I've managed to query both using HttpClient - for which one uses oAuth 2.0 bearer tokens, the other basic authentication.
I am able to query various functions on both oData feeds and get a valid JSON string returned. The issue I'm having is understanding the data models around them.
For one of them I created my own data model class and manually replicated the models (there is not much being offered by this API). I can successfully deserialise the JSON response to my manually typed model (although for single items I deserialise direct to the model (EmployeeModel) for lists I had to add a second class (ODataEmployeeModel) to strip out the JsonProperty("odata.context") string) like so
public class ODataEmployeeModel
{
[JsonProperty("odata.context")]
public string? Metadata { get; set; }
public List<EmployeeModel>? Value { get; set; }
}
public class EmployeeModel
{
public string? DisplayId { get; set; }
public string? Title......
}
The other is a well-developed API offing a lot of data documented in the $metadata including complex models. What is the best way to consume the $metadata?
I was hoping that I could scaffold classes to match the models / entities much like scaffolding from a database using EF but most of my reading (or at least my understanding of my reading) seems to indicate that I should add NuGet package and generate a proxy class and the data classes for the service all in one go.
This I assume this would mean that my own HttpClient code is moot? What (if any) is the preferred / better way to connect? I will be using various filters etc.. on the oData requests and I have these working perfectly with my typed HttpClient setup.........
Is the generated proxy from a plugin like ODataV4ClientGenerator the better way of doing things?
Any help / suggestions / guidance is much apricated.
You can use the dynamic type if you don't know what the object looks like.
Assuming the API returns a JSON object.
class Response
{
public int IKnowThisField { get; set; }
public dynamic ButIDontKnowThis { get; set; }
}
JsonConvert.Deserialize<Response>(data);

Read structured data from OPC UA server

I'm triying to read some data form an OPC UA server using opc-ua-client library. Managed to connect to server and read some simple variables, but facing issues when reading structured values. However, I'm able to browse those structured values using 3rd party tools, such as UAExpert.
This is the code snippet:
var readRequest = new ReadRequest
{
NodesToRead = new[] { new ReadValueId { NodeId = NodeId.Parse(nodeId), AttributeId = AttributeIds.Value } }
};
var response = channel.ReadAsync(readRequest).Result;
var result = response.Results[0].GetValueOrDefault<ExtensionObject>();
The point is: how should I cast the ExtensionObject into the underlying real object? Response's body is binary serialized into a System.Byte[] field, and don't know how to deserialize it. I know the fields and types of the structure, so defined it in the code (even decorating with the namespace provided by the server) as follow:
[BinaryEncodingId("nsu=urn:OMRON:NxOpcUaServer:FactoryAutomation;i=5005")]
private class MES_WRITE_STRUCT : Structure
{
uint Message_NUM { get; set; }
//Some other fields
DateTime Time_Stamp { get; set; }
}
Things I've tried (and failed) so far:
Brute-force cast:
var eObject = (MES_WRITE_STRUCT)result.GetValueOrDefault<ExtensionObject>();
Read the response as the expected type rather than using generic object:
var eObject = result.GetValueOrDefault<MES_WRITE_STRUCT>();
Use the Variant property rather than Value (same result as
using Value):
result.Variant.GetValue();
Create a binary reader and attempt to deserialize it into expected
class.
Maybe I'm using a wrong approach and structured values should be read in a different way. Or even the library does not support structured variables (not much documentation available). Or just using an incorrect type when defining custom class in .NET and hence casting is failing.
I'm totally stuck, any information or guidance is wellcome.
PS: I'm not tied to this library and can switch to another one (preferably with no licenses, but if really worths can consider buying).
One way would be to use the XML description of the information model (so called nodesets) you wish to consume and use the model compiler from OPC Foundation to generate C# classes out of it. Those classes can be integrated in your solution and used for deserialization.
And example (using the OPC Foundation libraries) could be found here
Another way is the OPC Foundation .NET Standard client which has an extension library nuget package called complex client. It contains the logic to read the structured type definition from a server from a dictionary (V1.03) or using DataTypeDefinition (V1.04).
Based on the obtained type definition the classes for the structured types can be emitted for encoding/decoding the byte string in the extension object at runtime. Please open issues if the complex client has difficulties to decode your structured type.

Get a specific part of my JSON data in 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;
}

JSON deserialization without using classes? (webservice client)

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

Possible to return Json data from C# class library

I am creating a report which requires returning Lists, and Json data to a web page. I'm working with a multi-tiered application. The web project is created using MVC but the heavy lifting is done in class libraries in separate projects.
I am returning a report object to my controller from a class library but I wanted to know is it possible to return a mix of Lists and Json in the model? Ideally I would like the report model to be similar to the following:
public class Report
{
public List<TopSellers> TopSellers { get; set; }
public List<MonthlySales> MonthlySales { get; set; }
public Json ShopSales { get; set; }
}
This way, the list stuff can be rendered as normal, but the jQuery could grab the Json being return to render the graphs I'm using.
Is this possible?
I have tried to declare it similar to this however the only option I get is 'JsonReaderWriterFactory'.
My exposure of Json up until now has been null so if someone could help me out, or point me in the right direction I'd be very grateful!
Thanks.
You could use the JSON.net library to serialize your object to a json string and set it to your ShopSales property.
http://json.codeplex.com/
report.OriginalList = objectToSerialize;
var jsonStr = JsonConvert.Serialize(objectToSerialize);
report.ShopSales = jsonStr;
return report;
On the client you can use the ShopSales property with jQuery.
The only approach I see here (and which I have also adopted once) is to create an HTTP Handler in your class library which intercepts certain requests and directly writes JSON onto the response (JSON.net is worth taking a look at).
Instead of the HTTP Handler you could also take a look on whether you could directly leverage the build-in ASP.net routing mechanism.
Your class library has then to be added as reference to a front-end project (i.e. ASP.net MVC / WebForms) obviously and the handler has to be registered there.

Categories