Deserializing a json string into structure results in exception - c#

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]

Related

Looping over long values from JSON and writing to console in 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());
}

How to serialize this C# return value into a JSON object?

I have this object value that is being returned and I would like to convert it into a useful JSON object that I can inspect and manipulate. Ultimately, my goal is to validate the values of username and accessKey. But 2 things are throwing this off. Double {{ makes it invalid JSON and sauce:options can't be converted into a property in a class.
{{
"browserName": "MicrosoftEdge",
"browserVersion": "latest",
"platformName": "Windows 10",
"sauce:options": {
"username": "test",
"accessKey": "123"
}
}}
Here is what I tried:
string output = JsonConvert.SerializeObject(SauceSession.Options.ConfiguredEdgeOptions);
This SauceSession.Options.ConfiguredEdgeOptions returns that object I mentioned above.
Got this back:
Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'BinaryLocation' on 'OpenQA.Selenium.Edge.EdgeOptions'.'
I also tried this as per suggestions:
var serialized = JsonConvert.SerializeObject(SauceSession.Options.ConfiguredEdgeOptions);
And got back this Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'BinaryLocation' on 'OpenQA.Selenium.Edge.EdgeOptions'.'
Since you cannot fix the source, you're going to have to apply a bodge to fix the JSON, for example this will work:
var fixedJson = sourceJson.Substring(1, Json.Length - 2);
Now you should have a couple of classes to hold your data, this way you can also cope with the unusual names:
public class Root
{
public string BrowserName { get; set; }
public string BrowserVersion { get; set; }
public string PlatformName { get; set; }
[JsonProperty("sauce:options")]
public Options SauceOptions { get; set; }
}
public class Options
{
public string Username { get; set; }
public string AccessKey { get; set; }
}
And now you should be able to deserialise like this:
var root = JsonConvert.DeserializeObject<Root>(fixedJson);

How to Deserialize JSON data? C#

Im getting a Json Data from an API and i have been trying to deserialize.
Json data:
{
   "items": [
      {
         "id": "1",
         "name": "samplename",
         "AddressList1": {
            "City": "Hyd",
            "State": "TN",
            "Country": "IN"
         },
         "Age": "10"
      },
      {
         "id": "2",
         "name": "samplename2",
         "AddressList1": {
            "City": "Hydd",
            "State": "TN",
            "Country": "IN"
         },
         "Age": "10"
      }
   ],
   "paging": {
      "cursors": {}
   }
}
Entities:
public class AddressList1
{
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class Item
{
public string id { get; set; }
public string name { get; set; }
public AddressList1 addressList1 { get; set; }
public string Age { get; set; }
}
public class Cursors
{
}
public class Paging
{
public Cursors cursors { get; set; }
}
public class Users
{
public List<Item> items { get; set; }
public Paging paging { get; set; }
}
C# code:
JsonConvert.DeserializeObject<List<Users>>(content);
Error Message:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.List`1[Entities.Users]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.
where am i doing wrong?
The following is a JSON-object; in your case a User
{ ... }
The following is a JSON-array; in your case an array of User
[ { ... }, { ... } ]
Thus if you want to deserialize the JSON you got into an array of Users this is not possible because you have no array in JSON.
Therefore the right code to deserialize is:
JsonConvert.DeserializeObject<Users>(content);
Furthermore your mapping is erroneous because in JSON there is a property AddressList1 and in the class it is called addressList1
Given your JSON, you would need a POCO object that contains a items member and a paging member.
JsonConvert.DeserializeObject<Users>(content);
should work.
Your Json string is good formatted and the entities are according to Json2Csharp good too.
but your problem is with the instruction JsonConvert.DeserializeObject<List<Users>>(content);
all that json that you have is only ONE User, and you are trying to get a list of them, there is the issue,
you can try instead with:
JsonConvert.DeserializeObject<Users>(content);
Try Below Code
JsonConvert.DeserializeObject<Users>(content);
Your entities(models) look just fine. If you are using, or were to use ASP.NET Web API 2, and your client is using the http verb post for example, this setup would work as Web API takes care of the object deserialization:
public HttpStatusCode Post(Item item)
{
Debug.Write(item.toString());
return HttpStatusCode.OK;
}
If you insist in deserializing manually then use the JavaScriptSerializer library which allows you to do things like:
Item item = new JavaScriptSerializer().Deserialize<Item>(content);
Notice that .Deserialize<T>() takes a generic which in your case it Item.
Hope that helps.

Parsing complex JSON text with Json.NET

I am writing a program to access Mediafire's web API and it's all going well, the only issue remaining is the response text in JSON format that I have difficulty parsing.
With API calls like creating a folder, I get a simple response which can be deserialized into a Dictionary<string,Dictionary<string,string>> and searched for values:
{"response":
{
"action":"folder\/create.php",
"name":"blargh",
"folder_key":"mmttuu769djo0",
"result":"Success",
"current_api_version":"2.14"
}
}
I would use it like this:
Dictionary<string,string> json = DeserializeJSON(text)["response"];
//DeserializeJSON is a method to shorten:
//JsonConvert.DeserializeObject<Dictionary<string,Dictionary<string,string>>(text)
I can then query for json["result"] and whatnot. With other API calls I get complex structures that I'm not sure how to handle. It's basically a bunch of key:value pairs, but some of the values are key:value pairs as well, which can't be put into a dictionary like I'm currently doing. I'm fairly new to C# so I'm not sure what to do here, is there some other data type like a Dictionary which doesn't have static types?
Here's the response:
{"response":
{
"action":"upload\/upload.php",
"doupload":
{
"result":"0",
"key":"89lh7760x4l"
},
"server":"live",
"result":"Success",
"current_api_version":"2.14"
}
}
My question would be: What is a good way to get this kind of data into a list that I can query for values?
What about creating a new class(s) to deal with the json? You can generate classes by using json2csharp using the example json.
public class Doupload
{
public string result { get; set; }
public string key { get; set; }
}
public class Response
{
public string action { get; set; }
public Doupload doupload { get; set; }
public string server { get; set; }
public string result { get; set; }
public string current_api_version { get; set; }
}
public class RootObject
{
public Response response { get; set; }
}
Then you can deserialise the json using:
JavaScriptSerializer serializer = new JavaScriptSerializer();
var something = serializer.Deserialize<RootObject>(jsonString);
I ended up finding out about the dynamic type - Deserializing the text into a Dictionary<string,dynamic> allows it to have multiple types where some can be dictionaries as well. I can query it as I would expect but I just need to be sure what values are returned with each API call, and I need to cast it to a string.
string upload_key = (string)json["response"]["doupload"]["key"] //89lh7760x4l

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