Undefined behaviour in Json - json

What should happen when the value of a property is set to undefined in a json string.
i.e:
{"Name":undefined}
The following example is using the json.net library. An exception is thrown when de-serializing the object.
JsonConvert.DeserializeObject<SimpleObject>("{\"Name\":undefined}");
public class SimpleObject
{
public string Name { get; set; }
}
Newtonsoft.Json.JsonReaderException was unhandled
Message=Error reading string. Unexpected token: Undefined. Path 'Value', line 1, position 18.
Source=Newtonsoft.Json
LineNumber=1
LinePosition=18
Path=Value

I think the error is fine.
Jsonlint.org throws an error too.
And reading the documentation on json.org the "value" element may have the following variants:
string
number
object
array
true
false
null
As you can see, undefined is NOT listed. Object does also not count as undefined.

Related

Is there a way to JSON.stringify an object and have it's type be JSON?

If I do this:
import { MyType } from 'somewhere';
class MyClass {
myObj: MyType = new MyType();
updateObject(newVal: string): void {
myObj.thing = newVal;
this.saveStuff(JSON.stringify(myObj));
}
saveStuff(json: JSON): void {
// http request...
}
}
I get an error that I'm passing a string, not JSON. (I understand that I am in fact passing a string) How can I make it take the string as JSON?
I tried casting the string as JSON, ie: JSON.stringify(foo) as JSON or <JSON> JSON.stringify(foo). But I get a "Type 'string' cannot be converted to type 'JSON'." error both ways.
What you are doing with the TypeScript type annotation is to announce the type you expect a value to have (you don't declare the type). More often than never it happens that you set a type annotation and when you run the code you discover that the actual type is something else.
In this case though the TS compiler can evaluate the types beforehand. It knows that JSON.stringify returns a string. Since you have annotated the saveStuff method to accept a JSON object, it will give you a compiler error for the type mismatch.
Regardless of its content, a string remains a string. It may contain JSON, XML or a poem. It will still be nothing else than a string. The JSON class is just a utility class that provides you with a way to serialize and deserialize a JavaScript object into and from a string (with JSON content).
JSON is not a type. When you parse a string by calling JSON.parse(str), what you get is an object literal.
In your code, as you call JSON.stringify(foo), you are converting the object literal foo to a string.
Thus, your saveStuff() receives a string.
JSON stands for JavaScript Object Notation. It is just a specification on how to represent an object.

Why is my Web API controller action not deserializing child properties of child properties?

I'm sending a json payload in a PUT request to a web API controller action. The action in question has a signature that looks like this:
public IHttpActionResult Post([FromBody]SaveThingRequest request)
SaveThingRequest looks something like this:
public class SaveThingRequest
{
public List<ElementInfo> Elements { get; set; }
public class ElementInfo
{
public List<ElementSettingInfo> Settings { get; set; }
public class ElementSettingInfo
{
public string Name { get; set; }
public string Value { get; set; }
}
}
}
I'm posting json in the body of the request that contains Elements that have Settings. I've confirmed this by manually deserializing in the controller action and confirming that the JSON has a structure that looks something like:
{
Elements: [
{
Settings: [
{
Name: 'Name 1',
Value: 'Value 1'
},
{
Name: 'Name 2',
Value: 'Value 2'
}
]
},
{
Settings: [
{
Name: 'Name 1',
Value: 'Value 1'
},
{
Name: 'Name 2',
Value: 'Value 2'
}
]
}
]
}
However, when .NET deserializes the payload and creates the SaveThingRequest, my Elements are populated but all of them have a null Settings property. I don't know how else to troubleshoot this. Does anyone have any thoughts on what might be going on here?
This question should be deleted. It works as advertised. My problem was that I had an additional property on the JSON called 'settings' (lower-case) that the deserializer was trying to match because NewtonSoft deserialization attempts a non-case sensitive match if a case sensitive one isn't found. I was able to discover what was happening by changing the signiture of the method to:
public IHttpActionResult Post([FromBody]string request)
and then adding this to the method implementation:
var result = JsonConvert.DeserializeObject<SaveThingRequest>(request);
I got a deserialization exception saying:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type
'System.Collections.Generic.List`1[Noteable.Contracts.ClinicalReports.SaveThingRequest+ElementInfo+ElementSettingInfo]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly. To fix this error either change the JSON to a JSON array
(e.g. [1,2,3]) or change the deserialized type so that it is a normal
.NET type (e.g. not a primitive type like integer, not a collection
type like an array or List) that can be deserialized from a JSON
object. JsonObjectAttribute can also be added to the type to force it
to deserialize from a JSON object. Path
'Elements[0].settings.TextSize', line 11, position 20.
The end of the message showed me what was being deserialized when the deserializer failed and pointed me in the right direction. =[
I was stuck in the same problem. However, the problem was something else.
In my case, the property that was not getting serialize was declared without public access specifier. I declared it to public, and it ran perfectly fine.
Hope this will help someone who got stuck in this situation. It took me 20 mins to reach this solution.
Make sure you didn't do something stupid like I did and sent a partially 'stringified' JSON string from the browser instead of a JSON object.
See the problem? I didn't at first until I tried deserializing it from a string and then I realized that shippingAddress itself was a string instead of being an actual JSON object. The rest of the object was proper JSON, but I accidentally serialized the shippingAddress field.
{
"fspID": 571285,
"foo": 444,
"shippingAddress": "{\"countryCode\":\"US\",\"firstName\":\"Test User\",\"lastName\":null,\"address1\":\"1 Main St4\",\"address2\":null,\"company\":null,\"city\":\"San Jose\",\"stateOrProvince\":\"California\",\"stateCd\":\"CA\",\"zipOrPostal\":\"95131\",\"countryName\":\"United States\",\"countryDesc\":\"United States\",\"phone\":null,\"phone2\":null}"
}
If you are using JSON.NET and the attribute [JsonProperty] to name a property – make sure you haven't accidentally copy pasted the same property twice and forgotten to update the string value.
[JsonProperty("billingAddress")]
public Address BillingAddress { get;set; }
[JsonProperty("billingAddress")]
public Address ShippingAddress { get;set; }
This will throw a Newtonsoft.Json.JsonSerializationException that won't actually be visible to you and will screw up the model.
I had the same problem that the child property was null. However the problem was something else.
I had only a getter on the property, once I added a setter as well, then the property was set as expected.

RestSharp deserialize JSON content(represent an object contains an byte array) error

The Client side receives a formal JSON content "{\"Id\":[1,2,3],\"Size\":56}", but get an error in deserialization the byte array.
1 Error occurs in the statement below
IRestResponse<key> response = client.Execute<key>(request);
2 Error message is "No parameterless constructor defined for this object."
3 The object class in client size is the same as it's in server side:
public class key
{
public byte[] id { get; set; }
public int Size { set; get; }
}
4 I've tried passing object that contains string and integer by JSON format and that's all fine but byte array.
JsonDeserializer from RestSharp can not deserialize array. Instead of byte[] use List<byte>. For more information see https://github.com/restsharp/RestSharp/wiki/Deserialization
I have run into this issue, too. My solution was to use RestSharp to perform a raw execute and use Json.NET to deserialize the result:
var response = client.Execute(request);
var keyResponse = JsonConvert.DeserializeObject<key>(response.Content);
keyResponse should now be an instance of your key class deserialized from the JSON content.
In addition to Chris Hogan's reply, I'd like to point out that I got this error when RestSharp incorrectly used the default serializer instead of the custom JSON.NET serializer I had assigned.
The reason for this was that I added a handler with content type application/json whereas the API I was getting the response from returned the content as text/json.
So by changing the AddHandler call to AddHandler("text/json", jsonDeserializer), I resolved the issue.

Gson deserialisation returns null

I have a problem on converting JSON string to object in Android. Here are the JSON structure and Java classes:
JSON:
{
"code":"SUCCEED",
"message":"",
"result":{
"ccahUserId": 111,
"ccahUserName":"your_name",
"userFirstName":"your_first_name",
"userLastName":"your_last_name",
//others
}
Java classes:
public class Result<T>{
public String code;
public String message;
public T result;
}
public class DeviceSetting
{
public long ccahUserId;
public String ccahUserName;
public String userFirstName;
public String userLastName;
//other members
}
Activity:
Gson gson = new Gson();
Result<DeviceSetting> setting = gson.fromJson(result, Result<DeviceSetting>.class);
When I deserialise the JSON string, code and message field were good but result field is null.
I am not familiar with Gson yet, so please help how to fix this problem?
Thanks in advance.
Likely the result field is null because it relies on the type parameter for Result.
From the GSON documentation for Gson.fromJson(JsonElement, Class<T>) (bolding is mine):
This method deserializes the Json read from the specified parse tree
into an object of the specified type. It is not suitable to use if the
specified class is a generic type since it will not have the generic
type information because of the Type Erasure feature of Java. Therefore, this method should not be used if the desired type is a generic type. Note that this method works fine if the any of the fields of the specified object are generics, just the object itself should not be a generic type. For the cases when the object is of generic type, invoke fromJson(JsonElement, Type).

FlexJSON - JSONDeserializer String Cannot be caste as Boolean

I am using FlexJson within my play framework application but at the point I am trying to deseralize the json string it throws a java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Boolean:
User user = new JSONDeserializer<User>()
.use(null, User.class).deserialize(body);
Body is the json string passed into the controller using standard jquery/ajax and
where User has the following boolean value declared:
public Boolean isCurrentUser;
Any ideas as to what I am doing wrong?
Thanks
In Json, Boolean is a type. Your JSon is:
{"user_id":"18","isCurrentUser":"true","title":"mr","description":"description"}
when it should be:
{"user_id":"18","isCurrentUser":true,"title":"mr","description":"description"}
Note that true is not a String, but a boolean. The parser fails because it finds a String instead of the expected boolean type. Fix the JSon generation to add a boolean, not a String.