I'm writing an application that posts and gets JSON to/from a backend in Visual C# 4.0.
Obviously, the easiest way to serialize/deserialize the JSON is System.Web.Script.Serialization.JavaScriptSerializer, but I'm having a weird error where it's throwing a ArgumentNullException, claiming that type is null.
When the following JSON is deserialized, it works fine:
{"results":[
{"Name":"Western Bulldogs",
"updatedAt":"2011-08-22T09:09:09.673Z",
"Nickname":"Bulldogs",
"RemoteId":44,
"Abbreviation":"WB",
"createdAt":"2011-08-22T09:09:09.673Z",
"objectId":"2iSK8FDTA6"}
]}
However, when deserializing the second one (with the nested dictionary), it fails with the type is null error.
{"results":[
{"EndDate":{"iso":"2011-09-06T00:00:00.000Z","__type":"Date"},
"Name":"Round 24",
"updatedAt":"2011-08-22T08:33:54.119Z",
"RemoteId":800,"createdAt":"2011-08-22T08:33:54.119Z",
"Season":{"className":"Season","__type":"Pointer","objectId":"WnsdqIlrd6"},
"Order":24,
"StartDate":{"iso":"2011-08-30T00:00:00.000Z","__type":"Date"},
"objectId":"bLdBfhagi9"}
]}
For reference, I'm deserializing with the following method for both queries:
JavaScriptSerializer jsSerialise = new JavaScriptSerializer();
ObjectIdContainerList contList = jsSerialise.Deserialize<ObjectIdContainerList>(responseString);
Where ObjectIdContainerList is as follows (note - it does not implement all the properties of the original JSON object because I am only interested in getting the objectId property):
[Serializable]
public class ObjectIdContainerList
{
public ObjectIdContainer[] results { get; set; }
}
[Serializable]
public class ObjectIdContainer
{
public String objectId { get; set; }
}
The first query deserialises without issue with exactly the same code and objects.
Any suggestions? Would I be best off just going to JSON.NET?
I don't understand what's the purpose of ObjectIdContainerList when you should be able to simply do this:
jsSerialise.Deserialize<List<ObjectIdContainer>>(responseString)
and get a List of ObjectIdContainer
I would also make sure that ObjectIdContainer has a property called "__type" that holds a string. I mention it because that's a weird name for a class property in C#.
EDIT: I just saw that you posted the rest of your code...
Are you saying that you expect to be able to deserialize the response string into an array of ObjectIdContainer where ObjectIdContainer only has a property called objectId? I would be very impressed if you can manage to make that work.
I remember Reflector once showed me that the implementation of the JavascriptSerializer basically uses reflection to serialize/deserialize objects; therefore, you need a corresponding class with the same property names as the ones defined in your JSON object or else it will fail.
I feel kind of bad for answering my own question, but I ended up solving the problem by using Json.Net to deserialise the object with almost exactly the same code and it worked.
I'm not inclined to say that this is a bug in the .Net framework, but it kind of feels that way.
Thanks to those who helped!
Related
I have a JSON data object and I pass that to my Controller using ([FromBody] Request request) in my route.
public class Request
{
public string[] Tests { get; set; }
}
But I get an error 61819Properties Should Not Return Arrays
From https://msdn.microsoft.com/en-us/library/0fss9skc.aspx, it said make the property a method or change the property to return a collection.
My question is when I change the property to a Method, ASP.net won't create a JSON object from JSON data in POST body. So what is the best way to fix this error for a JSON object?
Do you have the option of taking the error's second suggestion, and making the property a collection instead, like this?
public List<string> Tests { get; set; }
The simple solution:
As this not an error you can simply ignore it.
The less simple solution: All the CAxxxx warnings the visual studio spits out are Static Code Analysis warnings, which means the code still compiles, although by some code quality rules Microsoft has defined (All these CAs) you code is flawed. In many situations a property returning an array is a code smell, but as you pointed out yourself in this situation it is the way it needs to be done. So you can disable that warning using the SuppressMessageAttribute.
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public string[] Tests { get; set; }
I have this JSON container that has a strange field called "48x48" for a photoUrl.
using Newtonsoft.Json;
(...)
dynamic issuesJson = JsonConvert.DeserializeObject(responseIssues.Content);
foreach (dynamic issue in issuesJson.issues){
Console.WriteLine(issue.name); //works properly
Console.WriteLine(issue.48x48); //error -> expected;
}
For some reason Visual Studio doesn't accept the access to this runtime field of this dynamic object. How can I work around this problem?
Note: I cannot change the field name.
Thanks anyway.
For some reason Visual Studio doesn't accept the access to this runtime field of this dynamic object.
Well what you've provided is simply not valid C#. An identifier can't start with a digit. That's still enforced even when you're trying to resolve a member of dynamic.
We don't know what type you're using for issues, but basically you'll need to handle it as a key/value map which you can access by string. Quite how you do that will depend on the implementation of issue. It doesn't look like Json.NET guarantees anything there - you may be able to cast it to JObject, for example:
foreach (JObject issue in issuesJson.issues) {
Console.WriteLine(issue["48x48"]);
}
Field names cannot start with a number. Sorry, no way around it.
You'll have to consult the documentation of your deserializer to see how it takes care of cases like that. It may be as simple as renaming the field "_48x48".
EDIT: actually, based on your code, you probably don't have a class representing this JSON object; I'm leaving my answer anyway, in case it helps someone else.
As others have mentioned, a C# identifier can't start with a digit. You just need to rename 48x48 to a valid name in your class, and map it to the actual JSON name using the [JsonProperty] attribute:
[JsonProperty("48x48")]
public string _48x48 { get; set; }
I have used json2csharp to produce some nice c# class into which I can deserialize json.
It is actually working as expected EXCEPT that json2csharp named some of the fields invalid_name . I renamed those to valid csharp names but when serialized those class are null.
I found this other SO post... where one of the answerers said the following...
Keep in mind the class I have pasted below will not work directly,
because of the naming of some of the fields in the json. You may have
to rename them manually and map them.
This exactly describes my problem. Unfortunately, the answer gives no clues on actually HOW to "map them." So can someone tell me how to manually map some json arrays to c# classes.
I am using RestSharp deserializers, btw.
Any ideas?
If you are using JSON.NET as the basis or JSON parsing, you can rename your properties and then decorate them with attributes to align them back to the original JSON object.
An example is a property in JSON called 1 which is invalid in C#. This can be corrected using the following:
[JsonProperty("1")]
public int? One { get; set; }
There is also a JsonObject attribute if you want to edit at the class level, and also a JsonIgnore object to ignore serialisation of properties.
This may be too much trouble, but I have an object I'm trying to deserialize that looks like this:
{
"Status": { ... a status object ... }
"Data" : {... could be any one of 10 other data classes I have ... }
}
I want to deserialize this object into a response class that looks like this:
public class Response
{
public Status Status;
public Stream Data;
}
Then later deserialize the Data attribute into another class. However, if I make the type of the data attribute a Stream, I get a Security Exception when I try to deserialize. Likewise, if I make it a string, the deserialize just calls the toString() method on the data object (after deserializing it) and puts that as the attribute, which isn't helpful.
Is there any way to accomplish something like this? I'm trying to avoid having 10 different classes that all look a lot like Response but just have a different type for the Data attribute. If there's a way that I can dynamically set the type of the Data attribute that might also solve the situation.
Thanks for any help!
I always use Newtonsoft.Json.dll to solve this problem.
DataContractJsonSerializer this is nice class added in the .net framework which can be used to serialize/desirealize object into JSON.
Now following is the example i am trying
[Serializable] class User { public string name; public string userId; }
Now following is the output generated
Output : Notice structure where only "name" is expected instead of k__BackingField
Now this is the problem after digging so much i am not sure from where <> and _BackingField is coming ?
{
"<name>k__BackingField":"test user",
"<userId>k__BackingField":100001}
This is just an educated guess. I think it's because you're using public fields instead of properties for name and userid.
Edit: It appears it also has to do with the fact that you are using the [Serializable] attribute instead of [DataContract] and [DataMember]. Check out this post for more detail:
C# automatic property deserialization of JSON