Generate lightweight JSON using DataContractJsonSerializer - c#

I'm trying to generate JSON using C# and DataContractJsonSerializer in .Net 3.5. The problem is that I can't figure out how to build the structure correct for the result I need.
I've tried to reproduce PHP's associative arrays using both hashtables, list objects and arraylists but can't figure out how to generate my result in the best way using DataContractJsonSerializer without having to create my own recursive loop for building JSON.
The closest approach is using the a Dictionary < string, Dictionary < string, string>> aproach but the result is too big as I can't "name" the keys.
This is what I get:
[
{
"Key":"status",
"Value":[
{
"Key":"value",
"Value":"ok"
}
]
},
{
"Key":"1",
"Value":[
{
"Key":"name",
"Value":"Result1"
},
{
"Key":"details",
"Value":"Result 1 details"
}
]
},
{
"Key":"2",
"Value":[
{
"Key":"name",
"Value":"Result2"
},
{
"Key":"details",
"Value":"Result 2 details"
}
]
},
{
"Key":"caller",
"Value":[
{
"Key":"value",
"Value":"1135345"
}
]
}
]
This is what I want:
{
"status":"ok",
"response":[
{
"id":1,
"name":"Result1"
"details":"Result 1 details"
},
{
"id":2,
"name":"Result2"
"details":"Result 2 details"
},
{
"id":3,
"name":"Result3"
"details":"Result 3 details"
],
"caller":"1135345"
}
Does anybody have a clue how I can generate this piece of JSON using C# without having to load the entire Json.NET framework? I need this to be generated as fast as possible as this project aims to become an site search engine.

You should look at using the JavaScriptSerializer. It's part of the .NET framework (distributed in System.Web.Extensions). To get the result you want you can do this:
var results = new[]
{
new{id=1,name="Result 1"},
new{id=2,name="Result 2"},
new{id=3,name="Result 3"}
};
var js = new JavaScriptSerializer();
var result = js.Serialize(new
{
status = "ok",
response = results,
caller = 1135345
});
You can either use anonymous classes, or any existing ones. Works perfectly fine :)
The return value of this call would be:
{"status":"ok","response":[{"id":1,"name":"Result 1"},{"id":2,"name":"Result 2"},{"id":3,"name":"Result 3"}],"caller":1135345}

Using the JavaScriptSerializer rather than DataContractJsonSerializer on a Dictionary will remove the Key/Value json attributes and make them into a "keyed" array.
http://msdn.microsoft.com/en-us/library/bb412168.aspx
Have you attributed your classes with the [DataContract] and [DataMember] decorators?
http://msdn.microsoft.com/en-us/library/bb412179.aspx

Related

How to show json objects(with diffrent data fileds) in a datatable?

İ want to show json objects in a datatable. (C#.MVC) Due fact that json object have mostly different fileds according machines data they belong. For each json object i dont want to write a seperate class. How can i handle this json objects dynamically and show datatable in a single class?
Thanks in advance.
With Cinchoo ETL, an open source library, you can do it as follows
string json = #"{
""header"": ""myheader"",
""transaction"": {
""date"": ""2019-09-24"",
""items"": [
{
""number"": ""123"",
""unit"": ""EA"",
""qty"": 6
},
{
""number"": ""456"",
""unit"": ""CS"",
""qty"": 4
}
]
}
}";
using (var r = ChoJSONReader.LoadText(json))
{
var dt = r.Select(f => f.Flatten()).AsDataTable();
Console.WriteLine(dt.DumpAsJson());
}
Output:
[
{
"header": "myheader",
"transaction_date": "2019-09-24",
"transaction_items_0_number": "123",
"transaction_items_0_unit": "EA",
"transaction_items_0_qty": 6,
"transaction_items_1_number": "456",
"transaction_items_1_unit": "CS",
"transaction_items_1_qty": 4
}
]
Hope it helps.

JSON element reader .NET

I have a simple JSON example like this :
{
"items": {
"element": ["item 1","item 2"]
},
"name": "James"
}
and a JSON Schema like this :
{
'type': 'object',
'properties': {
'name': {'type':'string'},
'items': {
'type': 'object',
'properties':{
'element':{
'type':'array',
'items':[{'type':'string', 'type':'string'}]
}
}
}
},
'additionalProperties': false
}
Calling "IsValid()" method in JSON.NET using the given Schema and Data will return VALID.
Question :
How do I traverse and edit the elements inside JSON ?
My objective is to look-up values of node "element" in database and then replace it with a generalized value if they exists e.g "item 1" exists in database and will replaced with "general value A". However, "item 2" doesn't exist in database and should throw some kind of error message when IsValid() method is called.
Note that this is a desktop application using .NET 4.5 and JSON.NET library, and it will be used as a data-cleansing tool. I'm open to any kind of alternative libraries as long as they are compatible with .NET 4.5 though..
Not fully understand the part of your question with IsValid() issue, but if talk about traversing through json elements and editing, you can use 2 methods.
Install Newtonsoft.Json at first in Package-Manager in VS: Install-package newtonsoft.json.
Create class JsonItems, which describes your input JSON hierarchy
class JsonItems
{
public Items items;
public string name;
}
class Items
{
public List<string> elements { get; set; }
}
Now you can legally deserialize your json and edit result as any .net object.
string jsonItems = #"{
'items': {
'element': ['item 1','item 2']
},
'name': 'James'
}";
var result = JsonConvert.DeserializeObject<JsonItems>(jsonItems);
result.items = new Items
{
elements = new List<string> {"itemd 3", "item 4"}
};
2. The second way is more quick (in implementation), but less secuarble in runtime. With help of dynamic.
dynamic d = JObject.Parse(jsonItems);
d.items.element[1] = "item 3";

Using Dynamic types with JSON in C#

I have an ASP.NET MVC app. I am trying to hit an external web service from the controller in my app. Currently, I am hitting the web service like this:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync(GetServiceUrl());
dynamic data = System.Web.Helpers.Json.Decode(...)
}
The result from the web service can have three different schemas in JSON. They look like this;
schema 1
{
"request":"some info",
"value": [
{"id":1, name:"bill" },
{"id":2, name:"john" }
]
}
schema 2
{
"request":"some info",
"value": [
{ "orderId":"A12345", orderDate:"10-12-2014" },
{ "orderId":"B31234", orderDate:"11-01-2014" },
{ "orderId":"C36512", orderDate:"12-03-2014" },
]
}
schema 3
{
"request":"some info",
"value": [
{ "productId":"11-22-33", "name":"ball", "description":"a round thing" },
{ "productId":"3A-12-52", "name":"tire", "description":"keeps you moving" },
{ "productId":"7D-xy-23", "name":"plate", "description":"something to eat off of." },
]
}
I would like to avoid writing three separate classes if at all possible. I really only want to do two things: 1) count the number of objects in the value array. 2) Loop through the objects in the value array and print out some of the values via Razor.
Can I do these two things without creating 3 new classes? If so, how?
THank you!
Assuming you're using json.net, you can use JObject and JArray.
var json = #"{'value': [ { 'id' : 1}, { 'id' : 2 } ]}";
var jObject = JObject.Parse(json);
var values = (JArray) jObject["value"];
Console.WriteLine("Number of items: {0}", values.Count);
foreach (var value in values)
{
// do something with value.
}
If you're not using json.net, you could go with Robert Harvey's suggestion and use JavaScriptSerializer.
var jsonDict = serializer.Deserialize<IDictionary<string, object>>(json);
var array = (IEnumerable<object>) jsonDict["value"];

Json.NET SelectTokens not working if json contains empty array

I have a valid JSON object that contains multiple "en-US" keys, which I'm trying select. For that purpose I use the JsonPath
"$..en-US"
which is given to the SelectTokens procedure implemented by the Json.NET. It's a JSON framework for .NET . Everything is working fine and well as long as my JSON doesn't contain any empty array.
Here's an example:
var myJsonPath = "$..en-US";
var myJson =
#"{
'controls': [
{
'messages': {
'addSuggestion': {
'en-US': 'Add'
}
}
},
{
'header': {
'controls': []
},
'controls': [
{
'controls': [
{
'defaultCaption': {
'en-US': 'Sort by'
},
'sortOptions': [
{
'label': {
'en-US': 'Name'
}
}
]
}
]
}
]
}
]
}";
var jToken = JObject.Parse(myJson);
var tokens = jToken.SelectTokens(myJsonPath);
Here, the tokens variable will contain just one element! That will be the "en-US" occurence BEFORE the empty array in the 'controls' of the 'header' object. However, when I just leave this 'header' object out:
var myJson =
#"{
'controls': [
{
'messages': {
'addSuggestion': {
'en-US': 'Add'
}
}
},
{
'controls': [
{
'controls': [
{
'defaultCaption': {
'en-US': 'Sort by'
},
'sortOptions': [
{
'label': {
'en-US': 'Name'
}
}
]
}
]
}
]
}
]
}";
I will get all the 3 occurencies of the "en-US" as expected. Btw, if I validate my JsonPath on the first JSON object (i.e. which contains an empty array) in an online tool, then as expected, I get all the three "en-US" cases. This diverges from what I'm getting from the Json.NET. I'm wondering whether it's a bug or do I have to handle this case manually somehow?
This is a bug that has been fixed. Upgrade to the latest version of Json.NET.
If you're in the same situation as me where you're a bit stuck with respect to updating your version of Json.NET, you can work around the issue by doing something along the lines of this:
IEnumerable<JValue> vals = jToken
.Desecendants()
.Where(w => w is JProperty && w.Name=="en-US")
.Select(s => s.Value);
Hope that helps! The vals array will contain the same tokens you would have gotten using the selector you were trying to use before.

Can I LINQ a JSON?

This is the JSON I get from a request on .NET:
{
"id": "110355660738",
"picture": {
"data": {
"url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-prn2/1027085_12033235063_5234302342947_n.jpg",
"is_silhouette": false
}
}
}
and I'd like to catch the field "url", using (maybe?) LINQ. I do many request as this, that differents a bit. So I won't to create a C# Class and deserialize it every time.
Is it a way to extract a single field? Thank you!
No need for Linq, just use dynamic (using Json.Net)
dynamic obj = JObject.Parse(json);
Console.WriteLine((string)obj.picture.data.url);
Linq version would not be much readable
JObject jObj = JObject.Parse(json);
var url = (string)jObj.Descendants()
.OfType<JProperty>()
.Where(p => p.Name == "url")
.First()
.Value;
Documentation: LINQ to JSON
I would not recommend LINQ. I would recommend a JSON library such as newtonsoft.json.
So you can do this:
string json = #"{
""Name"": ""Apple"",
""Expiry"": "2008-12-28T00:00:00",
""Price"": 3.99,
""Sizes"": [
""Small"",
""Medium"",
""Large""
]
}";
JObject o = JObject.Parse(json);
string name = (string)o["Name"];
// Apple
JArray sizes = (JArray)o["Sizes"];
string smallest = (string)sizes[0];
// Small
Note:- this code has been copied from the samples present on the project site
http://james.newtonking.com/pages/json-net.aspx
In a bind you could always deserialize the JSON and serialize it to XML, and load the XML in a XDocument. Then you can use the classic Linq to XML. When you are done take the XML, deserialize it, and serialize it back to JSON to JSON. We used this technique to add JSON support to an application that was originally built for XML, it allowed near-zero modifications to get up and running.
You can easily query with LINQ like this
considering this JSON
{
"items": [
{
"id": "10",
"name": "one"
},
{
"id": "12",
"name": "two"
}
]
}
let's put it in a variable called json like this,
JObject json = JObject.Parse("{'items':[{'id':'10','name':'one'},{'id':'12','name':'two'}]}");
you can select all ids from the items where name is "one" using the following LINQ query
var Ids =
from item in json["items"]
where (string)item["name"] == "one"
select item["id"];
Then, you will have the result in an IEnumerable list

Categories

Resources