Looping over long values from JSON and writing to console in C# - c#

I have a JSON file structured like so in a file named 'Config.json':
{
"name": "Michael",
"ids": [111111, 222222, 333333, 444444, 555555]
}
I am deserializing it like so:
Config config = JsonConvert.DeserializeObject<Config>(File.ReadAllText("Config.json"));
I have a Config class like so:
class Config
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("ids")]
public long Ids{ get; set; }
}
How do I iterate over the ids and write them to console? I have tried this:
var ids = new List<long> { config.Ids};
foreach (long id in ids)
{
Console.WriteLine(id.ToString());
}
But I get an error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Int64' because the type requires a JSON primitive value (e.g. string, number, boolean, null) to deserialize correctly
I cannot figure out how to deserialize and write this...I have tried experimenting with different values (uint64) but the same error occurs.
Thanks so much!

Your ids property in your Json is an array (as indicated by the square brackets). To properly desierialize this Json, your model class should look like
public class Config
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("ids")]
public IEnumerable<long> Ids { get; set; }
}
Then, if you want to write all of the values to console
foreach (var id in config.Ids)
{
Console.WriteLine(id);
}

ids is an array.
Change public long Ids{ get; set; } to public long[] Ids { get; set; } and print them like this:
foreach (long id in config.Ids)
{
Console.WriteLine(id.ToString());
}

Related

Json.Net Deserialize dictionary without property name

I already looked at a lot of other questions with the same problem but never found a definitive solution that actually works for me. I tried using the JsonExtensionData Attribute, that doesn't work though since I can't convert my other data class to an object and it throws the Invalid extension data attribute on 'NAMESPACE'. Member 'Sols' type must implement IDictionary<string, JToken>. error.
My current data model class looks like this
public partial class Mars
{
public Dictionary<string, Sol> Sols { get; set; }
[JsonProperty("sol_keys")]
public List<long> SolKeys { get; set; }
}
public partial class Sol
{
[JsonProperty("AT")]
public At At { get; set; }
[JsonProperty("First_UTC")]
public DateTimeOffset FirstUtc { get; set; }
[JsonProperty("Last_UTC")]
public DateTimeOffset LastUtc { get; set; }
[JsonProperty("Season")]
public string Season { get; set; }
}
public partial class At
{
[JsonProperty("av")]
public double Av { get; set; }
[JsonProperty("ct")]
public long Ct { get; set; }
[JsonProperty("mn")]
public double Mn { get; set; }
[JsonProperty("mx")]
public double Mx { get; set; }
}
The json data looks like this
{
"651":
{
"AT":
{
"av": -61.957,
"ct": 302204,
"mn": -96.733,
"mx": -15.877
},
"First_UTC": "2020-09-25T02:42:14Z",
"Last_UTC": "2020-09-26T03:21:49Z",
"Season": "summer"
},
"652": {
"AT": {
"av": -65.002,
"ct": 278608,
"mn": -96.111,
"mx": -15.653
},
"First_UTC": "2020-09-26T03:21:50Z",
"Last_UTC": "2020-09-27T04:01:24Z",
"Season": "summer"
},
"sol_keys": [
"646",
"647",
"648",
"649",
"650",
"651",
"652"
]
}
I can't really modify the json data since I get it from an api.
I basically just want to select one of the numbers and then get the Sol data of that object.
Any help would be appreciated.
The JSON doesn't fit well with the C# type system. However, you can still use Json.Net to parse it. You just need to introduce some extra steps.
First step is to parse the JSON to a JObject:
var jObject = JsonConvert.DeserializeObject<JObject>(json);
Then you can extract the sol_keys:
var solKeys = jObject.GetValue("sol_keys").ToObject<long[]>();
Now it becomes a bit tricky. If you remove the sol_keys from the JSON (in this case the parsed JSON) it has the structure of a dictionary of Sol objects that you are able to parse:
jObject.Remove("sol_keys");
var mars = jObject.ToObject<Dictionary<long, Sol>>();
Now you have both solKeys and mars parsed from the JSON. Furthermore the solKeys and the keys in the dictionary share the same type (long).

Deserializing a json string into structure results in exception

I'm having issues mapping a json string returned from sql.
The structure of the object looks like this
public class OrderSummaryDto
{
public List<PrescriptionInfo> PrescriptionsInfo { get; set; }
public class PrescriptionInfo
{
public string Name { get; set; }
public AdministrationInfo Administration { get; set; }
public class AdministrationInfo
{
public string Instructions { get; set; }
public string PackageType { get; set; }
}
}
}
The json string returned from DB
[{"Name":"testName","Units":3,"Medium":"flower power","Administration":"{\"Instructions\":\"drIVnkLEm0b24OK9ceMeeF2fq\",\"PackageType\":\"case\"}"},{"Name":"testName","Units":3,"Medium":"flower power","Administration":"{\"Instructions\":\"drIVnkLEm0b24OK9ceMeeF2fq\",\"PackageType\":\"case\"}"}]
The Sql that generates the json string
(SELECT _co.[Name]
,_co.[Pharmacy_Instructions] AS [Administration]
FROM [dbo].[Compounds] _co
WHERE _co.[Id] = 1
FOR JSON PATH) AS [PrescriptionsInfo]
Pharmacy_Instructions is already a JSON formated string
Message "Could not cast or convert from System.String to
Models.Order.Summary.OrderSummaryDto+PrescriptionInfo+AdministrationInfo." string
Your JSON string is currently a list of PrescriptionInfo Objects, not a OrderSummary object that contains a list of PrescriptionInfo objects. In addition, some fields (Administration) are being treated as strings, instead of objects. The JSON needs to look like this to work properly:
{"PrescriptionsInfo": [{"Name":"testName","Units":3,"Medium":"flower power","Administration":{"Instructions":"drIVnkLEm0b24OK9ceMeeF2fq","PackageType":"case"}},{"Name":"testName","Units":3,"Medium":"flower power","Administration":{"Instructions":"drIVnkLEm0b24OK9ceMeeF2fq","PackageType":"case"}}]}
Or formatted:
{
"PrescriptionsInfo":[
{
"Name":"testName",
"Units":3,
"Medium":"flower power",
"Administration":{
"Instructions":"drIVnkLEm0b24OK9ceMeeF2fq",
"PackageType":"case"
}
},
{
"Name":"testName",
"Units":3,
"Medium":"flower power",
"Administration":{
"Instructions":"drIVnkLEm0b24OK9ceMeeF2fq",
"PackageType":"case"
}
}
]
}
In order to do this you will have to use aliases. Check out this MS guide
https://learn.microsoft.com/en-us/sql/relational-databases/json/format-nested-json-output-with-path-mode-sql-server?view=sql-server-2017
I am weak with JSON support in SQL, might ask with those tags, but it seems like it would be something similar to this.
(SELECT _co.[Name],
JSON_VALUE(_co.[Pharmacy_Instructions], '$.Instructions') AS "Administration.Instructions",
JSON_VALUE(_co.[Pharmacy_Instructions], '$.PackageType') AS "Administration.PackageType"
FROM [dbo].[Compounds] _co
WHERE _co.[Id] = 1
FOR JSON PATH) AS [PrescriptionsInfo]

Deserializing json - wrong type

Here's how I try to deserialize my json:
new JavaScriptSerializer().Deserialize<Dictionary<int, MyModel>>(myData);
Here's the class:
public class MyModel
{
public Dictionary<int, ItemModel> Translation { get; set; }
public int Id { get; set; }
}
public class ItemModel
{
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
}
And here's the json:
"[[],[],{"Translation":{"1":{"Name":"Bla1","ShortDescription":"bla1","LongDescription":"bla1"},"2":{"Name":"BlaUS1","ShortDescription":"BlaUS1","LongDescription":"BlaUS1"}},"Id":"12"},{"Translation":{"1":{"Name":"Bla22","ShortDescription":"bla22","LongDescription":"bla22"},"2":{"Name":"Bla2US2","ShortDescription":"Bla2US2","LongDescription":"Bla2US2"}},"Id":"13"}]"
and I get the error that the type is not supported for deserialization of an array.
Where is my error?
First of all your JSON looks a bit wrong to me. It is and array of 4 elements and 1st two elements are empty arrays but other two objects? I suspect your JSON should be something like that:
"[{"Translation":{"1":{"Name":"Bla1","ShortDescription":"bla1","LongDescription":"bla1"},"2":{"Name":"BlaUS1","ShortDescription":"BlaUS1","LongDescription":"BlaUS1"}},"Id":"12"},{"Translation":{"1":{"Name":"Bla22","ShortDescription":"bla22","LongDescription":"bla22"},"2":{"Name":"Bla2US2","ShortDescription":"Bla2US2","LongDescription":"Bla2US2"}},"Id":"13"}]"
Another issue is that you have Dictionary<int, ItemModel> but for serialization/deserialization you must have key of String or Object type.
Working example (providing that you changed from Dictionary<int, ItemModel> to Dictionary<object, ItemModel>):
string input = "[{\"Translation\":{\"1\":{\"Name\":\"Bla1\",\"ShortDescription\":\"bla1\",\"LongDescription\":\"bla1\"},\"2\":{\"Name\":\"BlaUS1\",\"ShortDescription\":\"BlaUS1\",\"LongDescription\":\"BlaUS1\"}},\"Id\":\"12\"},{\"Translation\":{\"1\":{\"Name\":\"Bla22\",\"ShortDescription\":\"bla22\",\"LongDescription\":\"bla22\"},\"2\":{\"Name\":\"Bla2US2\",\"ShortDescription\":\"Bla2US2\",\"LongDescription\":\"Bla2US2\"}},\"Id\":\"13\"}]";
List<MyModel> myModels = new JavaScriptSerializer().Deserialize<List<MyModel>>(input);
Your string suggests that what you have is a JSON array, eg:- [1,2,3]
but you are trying to deserialize it into a dictionary for which the json representation is akin to
{"1":"Hai","2":"Hello"}
obviously the library is throwing an error. May be why dont you use the following to deserialize the string.
new JavaScriptSerializer().Deserialize<List<MyModel>[]>(myData)
However, to use it you can't have empty arrays in the json, you have to fill them with default values for the properties.
To prove that the above works, try
"[{"Translation":{"1":{"Name":"Bla1","ShortDescription":"bla1","LongDescription":"bla1"},"2": {"Name":"BlaUS1","ShortDescription":"BlaUS1","LongDescription":"BlaUS1"}},"Id":"12"},{"Translation":{"1":{"Name":"Bla22","ShortDescription":"bla22","LongDescription":"bla22"},"2":{"Name":"Bla2US2","ShortDescription":"Bla2US2","LongDescription":"Bla2US2"}},"Id":"13"}]"
with
new JavaScriptSerializer().Deserialize<List<MyModel>>(myData)

Deserialize JSON string into a list for dropdownlist in C#

I have a windows form application and would like to deserialize a JSON string that I'm getting from a web address so that I can get just two values from it, how would I go about doing this?
Below is the code I have to get the JSON string, and if you go to the URL that it's getting, you can also see the JSON string. I want to just get the item name, and current price of it. Which you can see the price under the current key.
private void GrabPrices()
{
using (WebClient webClient = new System.Net.WebClient())
{
WebClient n = new WebClient();
var json = n.DownloadString("http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item=1513");
string valueOriginal = Convert.ToString(json);
Console.WriteLine(json);
}
}
It's also going to be iterating through a SQLite database and getting the same data for multiple items based on the item ID, which I'll be able to do myself.
EDIT I'd like to use JSON.Net if possible, I've been trying to use it and it seems easy enough, but I'm still having trouble.
Okay so first of all you need to know your JSON structure, sample:
[{
name: "Micheal",
age: 20
},
{
name: "Bob",
age: 24
}]
With this information you can derive a C# object
public class Person
{
public string Name {get;set;}
public int Age {get;set;}
}
Now you can use JSON.NET to deserialize your JSON into C#:
var people = JsonConvert.DeserializeObject<List<Person>>(jsonString);
If you look at the original JSON it is an array of objects, to deal with this I have used List<T>.
Key things to remember, you need to have the C# object mirror in properties that of the JSON object. If you don't have a list, then you don't need List<T>.
If your JSON objects have camel casing, and you want this converted to the C# conventions, then use this:
var people = JsonConvert.DeserializeObject<List<Person>>(
jsonString,
new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() });
First of all you need to create a class structure for the JSON
public class Wrapper
{
public Item item;
}
public class Item
{
public string icon { get; set; }
public string icon_large { get; set; }
public int id { get; set; }
public string type { get; set; }
public string typeIcon { get; set; }
public string name { get; set; }
public string description { get; set; }
public GrandExchange current { get; set; }
public GrandExchange today { get; set; }
public bool members { get; set; }
public GrandExchange day30 { get; set; }
public GrandExchange day90 { get; set; }
public GrandExchange day180 { get; set; }
}
public class GrandExchange
{
public string trend { get; set; }
public string price { get; set; }
}
Then you need to serialize the current item into a Wrapper class
var wrapper = JsonConvert.DeserializeObject<Wrapper>(json);
Then if you want multiple items in a list, you can do so with this code :
// Items to find
int[] itemIds = {1513, 1514, 1515, 1516, 1517};
// Create blank list
List<Item> items = new List<Item>();
foreach (int id in itemIds)
{
var n = new WebClient();
// Get JSON
var json = n.DownloadString(String.Format("http://services.runescape.com/m=itemdb_rs/api/catalogue/detail.json?item={0}", id));
// Parse to Item object
var wrapper = JsonConvert.DeserializeObject<Wrapper>(json);
// Append to list
items.Add(wrapper.item);
}
// Do something with list
It is also worth noting that Jagex limit how many times this API can be called from a certain IP within a time frame, going over that limit will block your IP for a certain amount of time. (Will try and find a reference for this)

Parsing JSON data in C#

I have a JSON data as follows
{"id": "367501354973","from": {
"name": "Bret Taylor",
"id": "220439" }
which is returned by an object(result) of IDictionary[String, Object]
In my C# code:
I have made a class for storing the JSON value which is as follows
public class SContent
{
public string id { get; set; }
public string from_name { get; set; }
public string from_id { get; set; }
}
My main C# function which stores the parses the JSON data and stores the value inside the class properties is as follows:
List<object> data = (List<object>)result["data"];
foreach (IDictionary<string, object> content in data)
{
SContent s = new SContent();
s.id = (string)content["id"];
s.from_name = (string)content["from.name"];
s.from_id = (string)content["from.id"];
}
When i execute this code, i get an exception saying System cannot find the Key "from.name" and "from.id"
When i comment the two lines (s.from_name = (string)content["from.name"];s.from_id = (string)content["from.id"];) my code runs fine.
I think i am not able to refer the nested JSON data properly.
Can anyone just validate it and please tell me how to refer nested data in JSON in C#?
Thanks
I'm not sure how you are parsing the JSON string. Are you using a class in the Framework to do the deserialization?
You could use the JavaScriptSerializer Class defined in the System.Web.Script.Serialization Namespace (you may need to add a reference to System.Web.dll)
Using that class, you would write your code like this:
public class SContent
{
public string id { get; set; }
public SFrom from { get; set; }
}
public class SFrom
{
public string name { get; set; }
public string id { get; set; }
}
Then deserialization looks like this:
var json = new JavaScriptSerializer();
var result = json.Deserialize<SContent>(/*...json text or stream...*/);
See JavaScriptSerializer on MSDN. You might also want to check out this similar question.

Categories