I am trying to Deserialize the string to JSON Object using JsonConvert.DeserializeObject like below:
var str = "{ Value: \"File\",Text: \"OWENS & MINOR INFANT - 2228548\"}";
agreementnodes = JsonConvert.DeserializeObject<List<AgreementNode>>("[" + str + "]");
When the json is converted to an array the properties are alphabetically ordered. Example : Even though Value is first and Text is in the string the properties are displayed like below:
Even in the class declaration, I Value is Firs and Text is second. But when de-serializing, the properties are sorted alphabetically.
[JsonProperty(Order = 9)]
public string Value { get; set; }
[JsonProperty(Order = 10)]
public string Text { get; set; }
Is there any way to retain the order of the properties in the resultant array like I want resultantarray[0] = Value and resultantarray1 = Text?
Nothing wrong with json.net serializer. It's automatically ordered by alphabetical in quickwatch and watch windows. Check System.Web.HttpContext.SystemWebAssembly if you want. It's not a deserialized code.
The ordering of properties are undefined according to the specification. In spite of that the most current ECMAScript (JavaScript) specification requires an ordered format which also enables new cool applications like:
https://cyberphone.github.io/openkeystore/resources/docs/jcs.html#ECMAScript_Compatibility_Mode
Related
I am having trouble parsing a JSON from the Alpha Vantage API. The output of the JSON is as follows
{
"Realtime Currency Exchange Rate": {
"1. From_Currency Code": "BTC",
"2. From_Currency Name": "Bitcoin",
"3. To_Currency Code": "CNY",
"4. To_Currency Name": "Chinese Yuan",
"5. Exchange Rate": "43211.50782620",
"6. Last Refreshed": "2018-04-11 17:48:12",
"7. Time Zone": "UTC"
}
}
I am parsing it like this
using (var wc = new System.Net.WebClient())
json = wc.DownloadString(link);
dynamic stuff = JsonConvert.DeserializeObject(json);
string test = stuff["Realtime Currency Exchange Rate"]["5. Exchange Rate"];
However when I run the code, I am getting this error
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot perform runtime binding on a null reference'
Anyone have any idea? If I print the value in a textbox, the value shows up but afterwards it shows that error. I am coding in c#
Thanks
Try creating an object to serialize to and use the JsonProperty attribute to map the json properties to the C# properties:
public class RealtimeCurrencyExchangeRate
{
[JsonProperty("1. From_Currency Code")]
public string CurrencyCode { get; set; }
}
Then use the correct type when deserializing.
var obj = JsonConvert.DeserializeObject<RealtimeCurrencyExchangeRate >(json);
References:
Spaces handling: Deserializing JSON when fieldnames contain spaces
DeserializeObject: https://www.newtonsoft.com/json/help/html/DeserializeObject.htm
Or, if you want to dynamically read the properties, you can create a custom contract resolver:
public class AlphaVantageApiContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
// derive the C#property name from the JSON property name
var cSharpPropertyName = propertyName;
// Remove all periods from the C#property name
cSharpPropertyName = cSharpPropertyName.Replace(".", "");
// replace all spaces with underscores
cSharpPropertyName = cSharpPropertyName .Replace(" ", "_");
// The value you return should map to the exact C# property name in your class so you need to create classes to map to.
return cSharpPropertyName;
}
}
and use this while deserializing:
var jsonSettings = new JsonSerializerSettings();
jsonSettings.ContractResolver = new AlphaVantageApiContractResolver();
var obj = JsonConvert.DeserializeObject<MyClass>(json, jsonSettings);
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_DefaultContractResolver.htm#!
You will still have to create classes that map to the objects but now you don't have to worry about the JsonProperty attribute on every property. Just remember to remove periods and replace spaces with underscores in your C# property names. You will also have to write some code to remove numbers at the beginning of property names because this isn't allowed in C#.
If you can't pre-define your classes, you will need to deserialize anonymous objects and work with that.
Your issue more than likely stems from your JSON. Though your JSON is valid, you violate a couple of principals which may be affecting the binder.
You have spaces for your property name, which are often translated into underscores.
You have a period in your property name, this also may interfere with the dot notation.
You could do the approach recommended by Kyle to bind. If you would like to use dynamic, then you could fix the above, then do the following syntax.
dynamic json = JsonConvert.Deserialize<object>(...);
var value = json.realTimeCurrencyExchangeRate.fromCurrencyCode;
The C# binder doesn't like a period when you utilize dot notation and spaces, when they're translated with underscores. So you could use your space, but the translation may be different. You would need to look closer at your object.
Is this json data format?
string json = {"answer":"Line 1","mark": 1},{"answer":"Line 3","mark": 1}
I try below code but it only working with one param. ex: {"answer":"Line 1","mark": 1}. I try split json string but it isn't best way.
JObject jObject = JObject.Parse(json );
string asw = jObject["answer"].ToString();
int mark = (int)jObject["mark"];
txtAnswer.Text = asw + "////" + mark + "\n";
This is a very basic JSON question which any number of tutorials could've answered for you.
Is it valid JSON ? No, and JSONLint could've told you that.
How do you read it in ?
First, wrap your JSON in square brackets so it's valid.
Then, define a class to store the records in:
public class Something
{
public string answer { get; set; }
public string mark { get; set; }
}
And finally, use JSON.Net to convert your string into a list of these records.
string json = "[{\"answer\":\"Line 1\",\"mark\": 1},{\"answer\":\"Line 3\",\"mark\": 1}]";
List<Something> records = JsonConvert.DeserializeObject<List<Something>>(json); // JSON.Net
foreach (Something record in records)
{
System.Diagnostics.Trace.WriteLine(string.Format("Answer: {0}, Mark: {1}", record.answer, record.mark));
}
Easy as that.
Is this json data format?
string json = {"answer":"Line 1","mark": 1},{"answer":"Line 3","mark": 1}
Nope, what you've got there doesn't look like valid C# or JSON. Try putting it inside a JSON array, then inside a proper string:
string json = "[{\"answer\":\"Line 1\",\"mark\": 1},{\"answer\":\"Line 3\",\"mark\": 1}]";
(Hope I've got all the escaping right there.)
That's the C# escaped equivalent of the following JSON:
[{"answer":"Line 1","mark": 1}, {"answer":"Line 3","mark": 1}]
Then read up on JObject.Parse()for more info.
Yes it is json format. But There are multiple objects. You are not looping through it. One way could be
dynamic dynJson = JsonConvert.DeserializeObject(json);
foreach (var item in dynJson)
{
Console.WriteLine("{0} {1}\n", item.answer, item.mark);
}
I'm having troubles de-serializing this JSON string using JSON.NET (note the quotes):
"[]"
Depending on which JSON validation website you go to, this is valid JSON (jsonlint for example says it is).
The JSON.NET code:
void Main()
{
string json = "\"[]\"";
var x = JsonConvert.DeserializeObject<User[]>(json);
Console.WriteLine(x);
}
// Define other methods and classes here
public class User
{
public string Id { get; set; }
public int Age { get; set; }
}
The exception
Error converting value "[]" to type 'UserQuery+User[]'. Path '', line 1, position 4.
Is there a way of forcing JSON.NET to parse this?
Part 1: Is "[]" valid JSON?
There are several documents and standards on JSON, and hundreds of parsers; and some of them suppose that JSON can only be object {} or an array [], but some allow single values like strings, numbers to be used as JSON.
Read this article, it widely describes this problem.
What is the minimum valid JSON?
This dispute on JSON validity is another question. In your case, it doesn't matter, because...
Part 2: why your code isn't working.
Even if we allow non-objects \ non-arrays to be valid JSON, then your JSON represents a single string equal to "[]". It could be anything else, not brackets, it is not an array notation, but just two symbols "[" and "]".
However, you try to parse this JSON as an array of objects, which will anyway result into error.
In other words, even if it is a valid JSON, then it is a valid JSON string, not JSON array.
var str1 = JSON.parse("\"[]\""),
str2 = JSON.parse("\"could be anything else, not brackets\""),
arr = JSON.parse("[]");
console.log(typeof str1);
console.log(typeof str2);
console.log(typeof arr);
var str1_s = JSON.stringify([]);
console.log("Valid JSON of an empty array: " + str1_s);
var arr_s = JSON.stringify("[]");
console.log("Partly valid JSON of a string '[]': " + arr_s);
Part 3: what should you do
The best idea - stop using invalid JSON as input. Tell whoever gave you this JSON that it is invalid JSON array and you cannot use it. You would be able to deserialize a JSON into your array of User if it was correct just like you use it:
string json = "[]";
var x = JsonConvert.DeserializeObject<User[]>(json);
Console.WriteLine(x);
If this JSON is provided from 3rd party services and you can do nothing about that, then you need to tidy it up and make it valid. Yeah, unfortunately, sometimes it happens.
How? It depends on what is your value when there ARE objects (users).
It may be a JSON-serialized JSON-string (double-serialized) like this, and then you need to deserialize a string, and then deserialize an array.
Or it can just have two odd quotes in the beginning and the end, and you can just remove them.
It is valid JSON, but the deserializer failes because the datatypes do not match.
"[]"
Is a string, so the deserializer wants to serialize it to a string.
[]
Is an empty array. So, in short, this should work:
string json = "[]";
var x = JsonConvert.DeserializeObject<User[]>(json);
Console.WriteLine(x);
Here is my json returned by php web application:
{"subtotal":475,"tax":47.5,"discount_section":[{"amount":237.5,"name":"test prior for percentage discount
"}],"grand_total_incl_tax":332.5}
I use c# and json.net to decode the abvoe json
var cart = webClient.DownloadString("http://localhost/m1/pos_addToCart.php?pidstr=" + pid_str);
dynamic result = JObject.Parse(cart);
But there is an error on this line:
order_discount_section.Text = result.discount_section;
Error:
Cannot implicitly convert type 'Newtonsoft.Json.Linq.JToken' to 'string'
How to convert this json to String like:
Key1 = Value1
Key2 = Value2
Key3 = Value3
Based upon your supplied json discount_section is a map so it can't be expressed as a string. It's like trying to convert a dictionary to a string or an array to a string.
If you want it as a string representation then adding ToString() after the result.discount_section (i.e. result.discount_section.ToString()) should accomplish that.
Though I would suggest that you either store the data through placeholder values such as:
string name = result.discount_section[0].name (same with amount but float/decimal/double...).
Or if you wanted it as text have it as
text = "Name: " + result.discount_section[0].name
+ "Amount: " + result.discount_section[0].amount.ToString();`
Obviously using a stringbuilder or other tool would be better (such as string.format) but I'll leave that as an 'exercise' to you.
Edit:
The for loop for all of the results.
totalText = ""
for (i = 0; i < result.discount_section.length; i++) {
totalText += "Name: " + result.discount_section[i].name + "Amount: " + result.discount_section[i].amount.ToString() + "\n";
}
Obviously if you wanted an array of strings then you would just build an array then just use i as your string array index as well.
Json.NET provides a correct behaviour.
As from your example string, it can be seen, that discount_section is a json array, or JArray, descendant of JToken after parsing to JObject.
If you want to access inner member of this array, as name for example, you should call it as
order_discount_section.Text = result.discount_section[0].name;
If you want to write the full notation of discount_section as is, you should explicitly call ToString method:
order_discount_section.Text = result.discount_section.ToString();
Although, dealing with dynamics is not useful, while your working with separate service responsing in JSON. It will be better to define a single class, which will handle json values, so you could not only look what json is passing, but to work with it
You may consider working with objects and deserialize using JsonConvert.DeserializeObject. Example:
class Discount
{
public Decimal Amount { get; set; }
public String Name { get; set; }
}
class Response
{
public Decimal Subtotal { get; set; }
public Decimal Tax { get; set; }
public List<Discount> Discount_section { get; set; }
public Grand_total_incl_tax { get; set; }
}
var response = JsonConvert.DeserializeObject<Response>(cart);
This approach is good when object structure is relatively fixed and has the following advantages:
clear structure
relevant errors when you have a type mismatch (JSON -> property)
result.discount_section is collection. you can not set directly to string variable.
try this.
var result= JObject.Parse(cart);
dynamic[] discountSection = result["discount_section"].ToArray<dynamic>();
decimal amount = discountSection[0].amount;
decimal name = discountSection[0].name;
for dictionary
Dictionary<string,decimal> discountDictionary = discountSection.ToDictionary<dynamic, string, decimal>((d) => d.name, (d) => d.amount);
I have a Web API middle layer which consumes an API which exposes a field which carries a timestamp as string (the field is string and it contains a value like "2016-05-31T14:12:45.753Z").
The proxy classes in the middle tier are generated using Visual Studio from Swagger endpoint and under the hood the object is deserialized using Json.NET.
I can see that the field was received as string (that's good):
inputObject {{ "When": "2016-05-31T14:12:45.753Z" }} Newtonsoft.Json.Linq.JToken {Newtonsoft.Json.Linq.JObject}
However, even though the target field is string the value of inputObject["When"] is a parsed as a timestamp.
inputObject["When"] {31/05/2016 14:12:45} Newtonsoft.Json.Linq.JToken {Newtonsoft.Json.Linq.JValue}
Then
JToken whenValue = inputObject["When"];
if (whenValue != null && whenValue.Type != JTokenType.Null)
{
this.When = ((string)whenValue);
}
In the end this.When is a string with value 31/05/2016 14:12:45.
Is there an option to prevent json.net from parsing the date and then casting it to string again?
Please remember that this transformation happens in auto generated code so I'm looking for some way of decorating the field on the server side which would make Swagger mark it somehow and then the generated classes would avoid the deserialize/serialize issue.
Something like:
[JsonProperty("This really is a string, leave it alone")]
public string When { get; private set; }
(Answering my own question)
I needed a solution quickly and this is my temporary solution, for the record.
I format the date as
"When": "2016-05-31 14:12:45"
and not
"When": "2016-05-31T14:12:45.753Z"
This prevents it from being interpreted. The front end (javascript) code knows that timestamps from the API are UTC and it appends 'Z' before transforming the timestamp to local time and formatting for display, e.g:
<td>{{vm.prettyDateTimeFormat(item.StatusDate+'Z')}}</td>
The ctrl code:
vm.prettyDateTimeFormat = function (dateString)
{
var momentDate = moment(dateString, "YYYY-MM-DD HH:mm:ssZZ");
if (typeof(momentDate) === "undefined" || (!momentDate.isValid()))
{
return dateString;
}
//The format needs to be sortable as it ends up in the grid.
var nicePrettyDate = momentDate.format('YYYY-MM-DD HH:mm:ss');
return nicePrettyDate;
}
As far as I don't like this solution it carried us through the demo. This issue is obviously in the back log now to be addressed properly.
[JsonIgnore]
public string When { get; private set; }