How to get JSON values into a string array? - c#

I am using VS2010 with C# 4. I have JSON similar to the following:
{"ItemDetails":{"Item":{"val": [
{"Description":"Desk1","Amount":"100.00"},
{"Description":"Desk2","Amount":"200.00"},
{"Description":"Desk3","Amount":"300.00"}]}}}
I want to get all the amount values into one string array like what is shown below:
amount={100.00,200.00,300.00}
How could I implement this? Do I have to loop through the JSON object or is there another way to do this?

I would recommend using NewtonSofts JSON library, but another (yet ugly) way is to use Regular Expressions.
var json = "{\"ItemDetails\":{\"Item\":{\"val\": [ " +
"{\"Description\":\"Desk1\",\"Amount\":\"100.00\",}," +
"{\"Description\":\"Desk2\",\"Amount\":\"200.00\",}," +
"{\"Description\":\"Desk3\",\"Amount\":\"300.00\"}}}";
// What I think you want
var amount = Regex.Matches(json, "Amount\":\"(.*?)\"").Cast<Match>().Select(m => m.Groups[1].Value).ToArray();
// Values 'converted' to json
var jsonAmount = "amount={" + string.Join(",", amount) + "}";

Using Json.Net you can do this with a LINQ-to-JSON query:
string json = #"
{
""ItemDetails"": {
""Item"": {
""val"": [
{
""Description"": ""Desk1"",
""Amount"": ""100.00""
},
{
""Description"": ""Desk2"",
""Amount"": ""200.00""
},
{
""Description"": ""Desk3"",
""Amount"": ""300.00""
}
]
}
}
}";
JToken token = JToken.Parse(json);
string[] amounts = token.SelectToken("ItemDetails.Item.val")
.Children()
.Select(t => t["Amount"].ToString())
.ToArray();
Console.WriteLine("amount={" + string.Join(",", amounts) + "}");
Output:
amount={100.00,200.00,300.00}

I am assuming you are not using JSON.NET. If this the case, then you can try it.
It has the following features -
LINQ to JSON
The JsonSerializer for quickly converting your .NET objects to JSON and back again
Json.NET can optionally produce well formatted, indented JSON for debugging or display
Attributes like JsonIgnore and JsonProperty can be added to a class to customize how a class is serialized
Ability to convert JSON to and from XML
Supports multiple platforms: .NET, Silverlight and the Compact Framework
Look at the example below.
In this example, JsonConvert object is used to convert an object to and from JSON. It has two static methods for this purpose. They are SerializeObject(Object obj) and DeserializeObject(String json) -
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Price = 3.99M;
product.Sizes = new string[] { "Small", "Medium", "Large" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Price": 3.99,
// "Sizes": [
// "Small",
// "Medium",
// "Large"
// ]
//}
Product deserializedProduct = JsonConvert.DeserializeObject(json);

Related

Sorting JObject inside array by a field value

I have a JSON string like below:
{
"MetaData": {
"ResourcesUsed": 1
},
"Result": [
{
"locations": [
{
"country": "Papua New Guinea",
"city": "Jacquinot Bay",
"locTypeAttributes": {
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-08T04:21:00-07:00",
},
"point": {
"coordinates": [
151.52,
-5.6
],
"type": "Point"
}
},{
"country": "Papua New Guinea2",
"city": "Jacquinot Bay2",
"locTypeAttributes": {
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-02T04:21:00-07:00",
},
"point": {
"coordinates": [
151.52,
-5.6
],
"type": "Point"
}
}
]
}
]
}
I converted it to a JSON object using Newtonsoft. What I want to do is to sort the locations array(s) inside the Result array by the utcDate field nested in each locations item. I found the following thread: C# Sort JSON string keys. However, I could not still implement it since I have arrays inside my object, while that question deals purely with sorting objects inside objects alphabetically by property name.
Here is a piece of code that I wrote so far:
public string GenerateJson()
{
var model = (JObject)JsonConvert.DeserializeObject(data);
Sort(model);
}
private void Sort(JObject jObj)
{
var props = jObj["Result"][0]["locations"].ToList();
foreach (var prop in props)
{
prop.Remove();
}
foreach (var prop in props.OrderBy(p => p.Name))
{
jObj.Add(prop);
if (prop.Value is JObject)
Sort((JObject)prop.Value);
if (prop.Value is JArray)
{
Int32 iCount = prop.Value.Count();
for (Int32 iIterator = 0; iIterator < iCount; iIterator++)
if (prop.Value[iIterator] is JObject)
Sort((JObject)prop.Value[iIterator]);
}
}
}
You can sort each individual "Result[*].locations" array using LINQ as follows:
// Load the JSON without parsing or converting any dates.
var model = JsonConvert.DeserializeObject<JObject>(data, new JsonSerializerSettings{ DateParseHandling = DateParseHandling.None });
// Construct a serializer that converts all DateTime values to UTC
var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings{ DateTimeZoneHandling = DateTimeZoneHandling.Utc });
foreach (var locations in model.SelectTokens("Result[*].locations").OfType<JArray>())
{
// Then sort the locations by utcDate converting the value to UTC at this time.
var query = from location in locations
let utcDate = location.SelectToken("locTypeAttributes.utcDate").ToObject<DateTime>(serializer)
orderby utcDate
select location;
locations.ReplaceAll(query.ToList());
}
Notes:
The JSON is initially loaded using DateParseHandling.None to prevent the "localDate" and "utcDate" strings from being prematurely interpreted as DateTime objects with a uniform DateTime.Kind.
(For a discussion of how Json.NET interprets strings that look like dates, see Serializing Dates in JSON.)
We then iterate through all "locations" arrays using SelectTokens("Result[*].locations") where [*] is the JSONPath wildcard character, selecting all entries in the "Results" array.
We then order each "locations" array by deserializing the nested locTypeAttributes.utcDate to a UTC date, then ordering using LINQ.
Finally the array is updated using JArray.ReplaceAll().
If any locTypeAttributes.utcDate property is missing, an exception will be thrown. You could instead deserialize to DateTime? if that is a possibility.
Working sample .Net fiddle here.

JSON JObject.Parse modifies json string

I have got incomming Json in format:
{
"Type": "value",
"Name": "MeteoStation",
"UniqueAdress": "2C:3A:E8:0F:10:76",
"valuesList": [{
"Value": 23.00,
"Unit": "C",
"Type": "temperature",
"SourceUniqAdress": "2C:3A:E8:0F:10:76",
"TimeCaptured": "2018-03-26T09:36:13.200Z"
}]
}
In my program, I want to create object IValuePacket that is one value in list of values.
JObject jobject = JObject.Parse(incomingJson);
var settings = new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
};
var incommingMessage = JsonConvert.DeserializeObject<MessageEncapsulation>(incomingJson);
string Type = incommingMessage.Type;
string name = incommingMessage.Name;
if (string.IsNullOrWhiteSpace(name))
name = "no name";
if (Type.ToLower().Equals("value")) {
var values = JsonConvert.DeserializeObject<List<IValuePacket>>(jobject["valuesList"].ToString());
}
Everything works fine untill I recieved exact this json as mention above.
JObject.Parse modifies value TimeCaptured and jobject looks like:
{
"Type": "value",
"Name": "Meteostation",
"UniqueAdress": "2C:3A:E8:0F:10:76",
"valuesList": [{
"Value": 23.00,
"Unit": "C",
"Type": "temperature",
"SourceUniqAdress": "2C:3A:E8:0F:10:76",
"TimeCaptured": "2018-03-26T09:36:13.2Z"
}]}
Thats not so much difference, but DateTime.ParseExact(value, "yyyy-MM-ddThh:mm:ss.fffZ", System.Globalization.CultureInfo.InvariantCulture); cannot parse new value. Actually, I am sending 201 ms instead of 200 ms. It works, but I want to have good time for future reasons.
Is there any way how to avoid changing in Json during parsing?
It does not really modify your string, it just parses your date string into DateTime object when you call JObject.Parse. If you do this:
var obj = JObject.Parse(json);
var values = (JArray) obj["valuesList"];
var time = (JValue) values[0]["TimeCaptured"];
Console.WriteLine(time.Value.GetType());
You notice that time.Value is of type DateTime. Then you do this:
JsonConvert.DeserializeObject<List<IValuePacket>>(jobject["valuesList"].ToString());
By doing that you convert valueList back to json, but now TimeCaptured is DateTime and not a string, so that DateTime object is converted to json string using whatever date time format is used by JSON.NET by default.
You can avoid parsing strings that look like dates to .NET DateTime objects by parsing json to JObject like this:
JObject obj;
using (var reader = new JsonTextReader(new StringReader(json))) {
// DateParseHandling.None is what you need
reader.DateParseHandling = DateParseHandling.None;
obj = JObject.Load(reader);
}
Then type of TimeCaptured will be string, as you expect.
Side note: there is no need to convert JToken back to string and then call JsonConvert.Deserialize on that string. Instead, do this:
var values = obj["valuesList"].ToObject<List<IValuePacket>>();

Remove property name from Json when its array

I am converting XML to JSON.
Input:
<emp
id="17377"/>
<CustomerList>
<Customer
id="67149"/>
<Customer id="64260"/>
</CustomerList>
OutPut:
"emp": {
"id": "17377"
},
"CustomerList": {
"Customer": [
{
"id": "67149"
},
{
"id": "64260"
}
]
}
But I need the below output. But I can not remove <Customer from <CustomerList> in the input. Also Please note that I need accept dynamic name
of array input. But always i want to remove the inner property name to be removed. in this example its Customer.But I may get MarkList->Mark then I need to remove remove Mark, etc.,:
"emp": {
"id": "17377"
},
"CustomerList": [
{
"id": "67149"
},
{
"id": "64260"
}
]
Is this possible please.
I use below code to convert XML to Json:
var xml = new XmlDocument();
xml.XmlResolver = null;
xml.LoadXml(richTextBox1.Text);
var jsonText = JsonConvert.SerializeXmlNode(xml,Newtonsoft.Json.Formatting.Indented);
Note:
One solution would be find the char "[" and remove before "[" and after "{".
This is not possible, as it is simply trying to change to JSON scheme in which it was orignally built.
what you can do, is use JObject to change the value of customer to feet your needs:
JObject rss = JObject.Parse(json);
JObject customers = rss.SelectToken("CustomerList");
customers ["Customer"] = newValue;
This is the snippet, modify this in your code to feet your needs.

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

Passing Array from Javascript to C#

I have a .js script that contain an array:
The output of the js is like:
var foo=
[
{
"bar1":"value1",
"bar2":"value2"
// And so on...
}
]
I have no access to the js source, so i cannot output as JSON and Deserialize.
I can only get this as a String using WebClient, but how i can parse it and create an Array/Dictionary and work on it inside C#?
You should consider calling WebClient.DownloadString . Then Parse using JSON.Net or whatever
As per the example provided over there
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
var foo = new JavaScriptSerializer().Deserialize<List<YourModelHere>>(YourString);
You can use a JavaScriptSerializer to deserialize that string:
string str=
#"var foo =
[
{
""bar1"":""value1"",
""bar2"":""value2""
}
]";
JavaScriptSerializer js = new JavaScriptSerializer();
var o = js.Deserialize<Dictionary<string,string>[]>(str.Substring(str.IndexOf('[')));
Result:
Dictionary<String,String> (2 items)
Key Value
------ --------
bar1 value1
bar2 value2

Categories

Resources