I have a problem when deserializing JSON with a string property value of "0". It gets deserialized to null.
{
"name":"Some name",
"isConfigProperty":true,
"displayProperty":false,
"default":"0"
}
This is my class to deserialize to:
public class PropertyModel
{
public string Name { get; set; }
public bool IsConfigProperty { get; set; }
public bool DisplayProperty { get; set; }
public string Default { get; set; }
}
When I change Default value from "0" to "1" or any other number/value it deserializes as it should. But when I change it to "0", I get null again.
Does anyone know about this? Is it possibly a bug in NewtonsoftJson or am I missing something?
Thank you.
You can use JsonConverterAttribute annotation: to define type for a property.
public enum UserStatus
{
NotConfirmed,
Active,
Deleted
}
public class User
{
public string UserName { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public UserStatus Status { get; set; }
}
Doc
it was solved. Something strange must have happened in Visual Studio debugger or maybe I just don't know that (I'm new in ASP.NET/Core/Microsoft) As it looks when debugging Blazor webassembly sometimes or in cases I don't know some variables are shown with null value when debugging... when in reallity they are not null.
I figured it out when I implemented logging to file and "default":"0" was 0 and not null.
Also thank you for all the answers you provided and sorry for causing this issue before I tried with all the solutions.
Related
I have is a list of properties, like public string RefID { get; set; } public bool myNiceProp { get; set; } and so on. I receive a string, and, some of those are in, for example "myNiceProp" = "1". First part of the problem, is to identify that I have the property "myNiceProp" and, if not, throw error, if yes, populate the value (and here is the second part of the problem, I must try to cast or somehow make sure the type is correct before I set the value to my property).I don't know which/how many key/value pairs are in the string.
Example:
public class InternationalSpaceStation
{
public Location position { get; set; }
public string missionName { get; set; }
public int missionNumber { get; set; }
}
public class Location
{
string coordinate { get; } = "Equatorial";
string inclination { get; set; }
string rightAscension { get; set; }
}
and my string looks like this:
{ "_report": {
"ISS": {
"inclination": "51.6430"
"rightAscension": "53.5336"
},
"status": {
"missionName": "Aquarius"
} }, "ccId": "42NM", }
So, I don't really care for the "_report" because has no value, but I do wnt to find all nested pairs of keys and values and assign their value to my properties, if I have them (if not, to throw error). I don't care if i have more properties - but, less, is a problem.
I thought to try with String.Split but I also have the problem of the type, so I must try to convert the string's value type to mine (in string, all values are in quotes).
Any help would be immensely appreciated..
I'm deserializing some JSON from a server which is, for the most part, simple:
{
"id": "ABC123"
"number" 1234,
"configured_perspective": "ComplexPerspective[WithOptions,Encoded]"
}
That "configured_perspective" property, however, is an unfortunate case of the server using a weirdly put-together string when a nested object would have been better.
To ease the suffering of our .NET users, I convert this into a custom class in my object model:
public class Example
{
public string id { get; set; }
public int number { get; set; }
public Perspective configured_perspective { get; set; }
}
// Note, instances of this class are immutable
public class Perspective
{
public CoreEnum base_perspective { get; }
public IEnumerable<OptionEnum> options { get; }
public Perspective(CoreEnum baseArg, IEnumerable<OptionEnum> options) { ... }
public Perspective(string stringRepresentation) {
//Parses that gross string to this nice class
}
public static implicit operator Perspective(string fromString) =>
new Perspective(fromString);
public override string ToString() =>
base_perspective + '[' + String.Join(",", options) + ']';
}
As you can see, I've put together a custom class Perspective that converts to and from the JSON string, but I can't seem to get Newtonsoft JSON to automatically convert the string to my Perspective class.
I tried getting it to call the string constructor with the [JsonConstructor] attribute, but it just calls the constructor with null, not with the string value present in the JSON.
I was under the impression (based on https://stackoverflow.com/a/34186322/529618) that JSON.NET would use implicit/explicit string conversion operators to convert a simple string in JSON to an instance of the target type when available, but it seems to ignore it, and just returns the error:
Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Perspective. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'configured_perspective'
I'm trying to avoid resorting to writing a custom JsonConverter for my Example class - I was pretty sure there would be an out-of-the-box way to convert simple string values to a non-string property type, I just haven't found it yet.
I actually wrote out a custom serializer class before doing reading the last of your article, but I then had an idea.
What if we modified example to not serialize it to Perspective? And we were somewhat lazy about it?
public class Example
{
public string id { get; set; }
public int number { get; set; }
public string configured_perspective { get; set; }
private Perspective _configuredPespective;
[JsonIgnore]
public Perspective ConfiguredPerspective => _configuredPerspective == null ? new Perspective(configured_persective) : _configuredPerspective;
}
It's not perfect, and we hold onto the string wasting memory, but it might work for you as a work-around.
Currently I'm using the following variation on #Jlalonde's suggestion - tweaked such that the user experience doesn't change, taking advantage of the fact that JSON.NET looks for private properties as well.
public class Example
{
public string id { get; set; }
public int number { get; set; }
[JsonIgnore]
public Perspective configured_perspective { get; set; }
[DataMember(Name = "configured_perspective")]
private string configured_perspective_serialized
{
get => configured_perspective?.ToString();
set => configured_perspective = value == null ? null : new Perspective(value);
}
}
I am able to get a JSON object with a list of surveys having a set of attributes for each of them. I have a class defined for surveys where I am defining all the survey attributes based on the obtained JSON object. I am facing an error while defining question.id attribute. Please suggest me the best way to solve this problem.
JSON Data:
"surveys":
{
"id": 20128672,
"trueFalse": false,
"question": "Any accidents on site today?",
"question.id": 1097329,
"question.tag": 0,
"images": [],
"videos": []
},
Survey class:
public class survey
{
public string id { get; set; }
public Nullable<bool> trueFalse { get; set; }
public string question { get; set; }
public string question.id { get; set; } //error in writing the question id attribute
public string desc { get; set; }
//public bool trueFalse { get; set; }
public string FormattedAnswer
{
get
{
if (trueFalse == null) return "NA";
return trueFalse == true ? "YES" : "NO";
}
}
}
I'm not sure what json lib you're using here but assuming it's json.net you can resolve this with a simple annotation mapping the json fields name to the C# property, the name you're giving that property in C# is not valid which is why you're getting the error, no periods in field names.
[JsonProperty("question.id")]
public int id { get; set; }
Also, I modified your type because it was wrong too, the json value is an int, not a string. If you're not using json.net, I'm sure you'll find similar features in the lib you are using, google json annotation or something along those lines with the packages name to find appropriate docs.
i tried to Deserialize this string :
string _jsonObject = {\"Ad\":{\"Type\":\"Request"\,
\"IdAd\":\"xxx#xxx.com\",
\"Category\":\"cat\",
\"SubCategory\":\"subcat\"},
\"Position\":{\"Latitude\":\"38.255\",
\"Longitude\":\"1.2\",
\"Imei\":\"0123456789\"};
}";
Message _message = JsonConvert.DeserializeObject<Message>(_jsonObject);
Works pretty for "Ad" but not instanciate "Position".
Any idea ?
I forgot to make the properties public. Don't forget to do that...
In the interest of helping others that may be experiencing this issue, or one related to it...
In my case, I had an object with an array of other objects, and one of the reference-type properties on those sub-objects was always null after deserialization. I tried all kinds of things, including downloading the JSON.Net source and stepping through it to find the failure point.
To make a long story short, the problem was, of course, my own. Here is a highly simplified version of my JSON and classes.
JSON
{
"$id": "1",
"RowCount": 10,
"Rows": [{
"$id": 2",
"ItemId": "1",
"ItemName": "Some Item",
"Owner": {
"Name": "John Doe",
"Id": "711D04F5-586F-4FD4-8369-4C00B51DD86F",
// other properties...
},
"OwnerId": "711D04F5-586F-4FD4-8369-4C00B51DD86F"
},
// more rows
]
}
Classes
public class Items
{
public int RowCount { get; set; }
public IEnumerable<Item> Rows { get; set; }
}
public class Item
{
private string ownerId;
public string ItemId { get; set; }
public string ItemName { get; set; }
public Person Owner { get; set; }
public string OwnerId
{
get { return this.ownerId; }
set {
if (value != this.ownerId)
{
this.Owner = null;
}
this.ownerId = value;
}
}
}
public class Person
{
public string Name { get; set; }
public string Id { get; set; }
// other properties
}
What was happening is that, because the Owner property appeared in the JSON prior to the OwnerId property, when the OwnerId property was set, the setter code determined that the current value was not the same as the value being set (since the current value was null), so it set the Owner property to null.
To fix it I also check the value being set against the id of the Owner object as well, and skip setting Owner to null if they are the same.
Admittedly, the cause of my problem may not be the same for everyone, but this is at least a cautionary tale to double-check what is happening when your objects are being initialized during deserialization.
I don't know how you are trying to deserialize, but this should work....
string json = "{\"Ad\":{\"Type\":\"Request\", \"IdAd\":\"xxx#xxx.com\", \"Category\":\"cat\", \"SubCategory\":\"subcat\"},\"Position\":{\"Latitude\":\"38.255\", \"Longitude\":\"1.2\", \"Imei\":\"0123456789\"}}";
var obj = JsonConvert.DeserializeObject<RootObject>(json);
public class Ad
{
public string Type { get; set; }
public string IdAd { get; set; }
public string Category { get; set; }
public string SubCategory { get; set; }
}
public class Position
{
public string Latitude { get; set; }
public string Longitude { get; set; }
public string Imei { get; set; }
}
public class RootObject
{
public Ad Ad { get; set; }
public Position Position { get; set; }
}
In my case, my class properties had internal setters and after setting them public the problem solved.
In my case there is a more subtle error. It is easy to add leading or trailing spaces in the json keys by mistake. When that happens, the key is not recognized and attempting to deserialize it sets the value to null.
For example: {" id": 123}
This id field is not recognized because of the leading space " id". To fix it, fix the json to have instead "id".
Make sure the name of array in JSON matches with property name in your class
Illustrating (Look for "Components"):
JSON:
{
"Components": [
{
"Attribute1": "ABC",
"Attribute2": "XYZ"
}
]
}
Class:
public class MyClass
{
public IList<Component> Components { get; set; }
}
Deserialize:
JsonConvert.DeserializeObject<MyClass>(File.ReadAllText(#"ComponentSet.json"))
My problem was that I was including the class name at the beginning of my JSON string. I had copy-pasted from the serialized output of another class that contained the one I wanted to deserialize and I had purposefully included the class name thinking this was the correct JSON string. Once I removed the class name from my JSON string, it deserialized just fine.
This article was helpful in realizing this: https://social.msdn.microsoft.com/Forums/windowsapps/en-US/4d766a28-ff38-477f-8abf-48ed01f74cd2/jsonconvertdeserializeobjectlttgtjsonstring-returning-all-propertieslttgt-as-null?forum=wpdevelop
I did not see this answer here so I am including it hoping that it helps those who made the same silly mistake as me.
I've never had any issues using Newtonsoft.Json, but decided to go with built in json libraries in latest project. Ended up with null result. Turns out the following will fail:
JSON:
{
"myProperty": "abc"
}
CLASS:
public void MyClass
{
public string MyProperty { get; set; }
}
Why does it fail? "myProperty" in json is camel case (starts with lower case letter), while MyProperty in MyClass starts with upper case letter. If you make both cases the same it works. I tried figuring out how to configure case insensitivity for the entire app, but apparently that's not possible to do, so I went back to Newtonsoft.JSON and the problem went away.
In my case, it was because I did not have a public constructor on my class.
This is what my class originally looked like:
public class TreeGroup
{
public string Name { get; set; }
public SiteGroup Group { get; set; }
public List<TreeMimicObject> Children { get; set; }
public TreeGroup(SiteGroup item)
{
// Notice this constructor takes a SiteGroup object and there
// is no default constructor
}
}
so I changed the class from the above to this:
public class TreeGroup
{
public string Name { get; set; }
public SiteGroup Group { get; set; }
public List<TreeMimicObject> Children { get; set; }
public TreeGroup()
{
// Added this default constructor here!!
}
public TreeGroup(SiteGroup item)
{
// ...
}
}
and it worked!
In my case the problem was deserializeobject return null when try to convert null value from json to int.
public class ItemCalcResModel
{
public int cartId;
}
I solved the problem by enable nullable in project:
#nullable enable
public class ItemCalcResModel
{
public int? cartId;
}
I have a JSON response like this
{
car:100,
house:200,
bike:300
}
But sometimes some of the properties doesn't come in the response. Like this (house is missing)
{
car:100,
bike:300
}
I'm deserializing with JsonConvert.DeserializeObject<Test>(json);
with this Test model
[JsonObject(MemberSerialization.OptIn)]
public class Test
{
[JsonProperty(PropertyName = "car")]
public int Car{ get; set; }
[JsonProperty(PropertyName = "house")]
public int House{ get; set; }
[JsonProperty(PropertyName = "bike")]
public int Bike{ get; set; }
}
Now the problem:
In the second example, where house is missing I'm stil getting the object test to have the propery House set in 0.
There is any way to make this properties optional, I want my model doesn't have the missing property.
Other thought
While I was writing this post I thought that maybe this does't make any sense at all, maybe the model is the 'model' why it should be different in different instances..may be is just wrong.
Any answer will be much apreciated.
thanks
The default value of int is 0. If House is optional, make it nullable.
[JsonProperty(PropertyName="house")]
public int? House { get; set; }
Change your properties to be nullable types - for example int? House { get; set; }