JsonConvert.DeserializeObject<T> doesn't take into account property names [duplicate] - c#

This question already has answers here:
Detect if deserialized object is missing a field with the JsonConvert class in Json.NET
(5 answers)
Closed 5 years ago.
I have a simple class I want to deserialize a json string into :
public class ConnectClientResponse
{
public bool result { get; set; }
}
Call of the Deserialize method :
try
{
var response = JsonConvert.DeserializeObject<ConnectClientResponse>(jsonString);
}
catch (JsonSerializationException)
{
// Exception should be thrown
}
The issue is when the json string has the same form as the ConnectClientResponse class but the property name is not the same, no exception is thrown.
Is this a normal behaviour ? If so, how can I check if the properties names are the same ?
Exemple of invalid json, the property name doesn't match the ConnectClientResponse "result" property name :
{
"test" : true
}

Your actual problem is not that there's a "similar" property, but that your property isn't mandatory.
If you want certain properties to be mandatory, mark it with the JsonProperty attribute, e.g. [JsonProperty(Required = Required.Always)]. You can also use the value Required.AllowNull instead, if null values should be valid, as long as the property name is there.

You can use the MissingMemberHandling on JsonSerializerSettings to control this behaviour. https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_MissingMemberHandling.htm

Related

Using JsonConverter on a property that is sometimes missing, as well as checking for single item or array

In the Json deserialization model, I have a class member that can be a single item or an array, thus I use a JsonConverter to deal with it.
However, sometimes the entire property is missing in the response as well. The model has a property that the Json response sometimes does not, so I am using [JsonProperty(Required = Required.Always)].
public class Reservation
{
[JsonConverter(typeof(SingleOrArrayConverter<Resource_Reservation>))]
[JsonProperty(Required = Required.Always)]
public List<Resource_Reservation> resource_reservation { get; set; }
The problem is when missing class property passes through the ReadJson method in the JsonConverter, it raises exception.
My question is whether I can add missing property logic check in the JsonConverter, or do I need to deal with the exception as is.

JSON and VS C# objects and names [duplicate]

This question already has answers here:
How can I use a reserved keyword as an identifier in my JSON model class?
(3 answers)
Closed 2 years ago.
I need to serialize a JSON string containing the following:
{
commandId;
id;
params:
{
userId;
password;
}``
}
The code I was given uses Qt and they declare a QJsonObject paramsObj and a QJsonObject cmdObj;
they fill the field values and finally perform a cmdObj.insert("params", QJsonValue(paramsObj));
params is a keyword for VS and C# so I can't declare a class with that name, but this is the way the device will understand my JSON strings.
I am fairly new to JSON and looked at the .Net class and the Newtonsoft library but can't find how to perform the insert of a JSON object inside another, assigning an arbitrary name to it.
Can anyone shed some light?
Thank you.
You just need to escape params with # like this:
public class MyObject
{
public Params #params { get; set; }
}
This produces:
{
"params": {}
}
Or use Params as property name and use CamelCasePropertyNamesContractResolver.

How to unset a property on a Delta object

I am using Azure Mobile App Services and in the PATCH method I receive as body an object of type Delta (see MSDN).
I receive some fields with null values that I would like to remove from the Delta input object: how can I do this action?
e.g. I have a JSON input like
{
"Content":"test",
"CreatedAt":null
...
}
this maps an Entity that inherits from Microsoft.Azure.Mobile.Server.EntityData
e.g.
public class MyBean : EntityData
{
public MyBean() { }
public string Content { get; set; }
}
I would like to remove the field "CreatedAt", which by the way is declared in the EntityData parent object, part of the Microsoft library (therefore I don't have direct access to it).
I don't think you should try to remove the CreatedAt, but instead, take the incoming Delta and create a new one. You could either include the fields you wanted or exclude the ones you don't want.
var newDelta = new Delta<MyBean>();
foreach(var fieldName in patchDelta.GetChangedPropertyNames()){
if(fieldName != "CreatedAt"){
if(patchDelta.TryGetPropertyValue(fieldName, out object fieldValue)){
newDelta.TrySetPropertyValue(fieldNAme,fieldValue);
}
}
}
If you are using the Newtonsoft.Json to serialize the Entity then you can use conditional serialization of a property.
To conditionally serialize a property, add a method that returns
boolean with the same name as the property and then prefix the method
name with ShouldSerialize. The result of the method determines whether
the property is serialized. If the method returns true then the
property will be serialized, if it returns false then the property
will be skipped.
public class MyBean : EntityData
{
public MyBean() { }
public string Content { get; set; }
public bool ShouldSerializeCreatedAt()
{
return false;
// Or you can add some condition to whether serialize the property or not on runtime
}
}

JSON.NET serialization of type derived from List<T> [duplicate]

This question already has answers here:
How to serialize/deserialize a custom collection with additional properties using Json.Net
(6 answers)
How do I get json.net to serialize members of a class deriving from List<T>?
(3 answers)
Closed 5 years ago.
We're switching our cache system over from a binary serializer (the one AppFabric uses) to a JSON serializer (For use with Redis) and I'm running into some incompatibilities with a few object types. The general idea is the same, we have a class that looks something like this:
[Serializable]
public class ActivityMeasurementIndexes : List<ActivityMeasurementIndex>
{
public int Id { get; set; }
public DateTime lastDbRead { get; set; }
public ActivityMeasurementIndexes()
{
lastDbRead = DateTime.Now;
}
}
The binary serializer will serialize and deserialize the object just fine. However, when I try to serialize the object with JSON.NET, I get:
var testObject = new ActivityMeasurementIndexes { Id = 5 };
Newtonsoft.Json.JsonConvert.SerializeObject(testObject);
"[]"
So, JSON.NET is basically serializing the base List<T> but the properties in the derived type are getting lost. I could probably refactor this class so it has a public List<ActivityMeasurementIndex> Items { get; set } instead, but we have quite a few of these classes and tons of code that would also have to be refactored.
Is there a good approach to handle this? I don't really care how the JSON looks as long as I can serialize and deserialize the base list as well as the properties on the class. I'm guessing I would need to write some sort of custom converter, or maybe there's something JSON.NET can do out of the box to help me out. Any hints for stuff to read up on would be great!

Ignoring JSON enum value that doesn't exist in target model class during deserialization [duplicate]

This question already has answers here:
How can I ignore unknown enum values during json deserialization?
(6 answers)
Closed 5 years ago.
So I'm working on a API wrapper with C#, I deserialize JSON data to a response model class using Newtonsoft.Json library. In the response model class, I have a list of sub-items, which each of contain a list of sub-items. These are defined like this:
public List<StatModel> Stats { get; set; }
each StatModel has a property which basically equals the name:
public Stat Stat { get; set; }
these are automatically deserialized, because each Stat is defined in an enum like this:
[EnumMember(Value = "Avg Walk Distance")]
AverageWalkDistance,
Now the problem is, if something changes in the actual API, the wrapper doesn't work since it doesn't have definition for the specified Stat. So this means if they add a new Stat to the API, the wrapper won't work until I manually add definition for it, like in the above code block.
So the question is, how can I ignore values that don't have corresponding Stat property available, or can I somehow re-design the whole thing so this doesn't happen? I'm guessing I have to define all new values by myself either way.
Here's the project on GitHub to get a better understanding of what I actually mean: https://github.com/eklypss/PUBGSharp
The Requester does the deserializing and returns a StatResponse, which has a list of sub-items called StatsRoot which each have their own list of StatModels which are the actual stat objects causing this issue. Each type of Stat is defined in the Enum/Stat.cs file.
If you don't want to create your own tolerant version of StringEnumConverter, you could use Json.NET's exception handling features:
public class StatModel
{
const string StatName = "label";
[JsonProperty(StatName)]
[JsonConverter(typeof(StringEnumConverter))]
public Stat Stat { get; set; }
public string Value { get; set; }
public int? Rank { get; set; }
public double? Percentile { get; set; }
[OnError]
void OnError(StreamingContext context, ErrorContext errorContext)
{
if (errorContext.OriginalObject == this && StatName.Equals(errorContext.Member))
{
errorContext.Handled = true;
}
}
}
When an exception is thrown while deserializing StatModel or any of its nested objects, its OnError() method will be called to possibly handle the error. The method checks to see whether the exception was thrown
While deserializing this specific object, AND
While deserializing the "label" member.
If so, the exception is swallowed. You could also take the opportunity to set a flag in the model indicating that the Stat property was invalid.
You can have json.net ignore missing members.
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore
};
var json = JsonConvert.DeserializeObject<MyClass>(jsonStr, settings);
Refer to the question below, this guy had same issues as you have.
How can I ignore unknown enum values during json deserialization?
However,
Even if you somehow manage to ignore new Stats, it's not good for your wrapper as consumers of your wrapper need to wait for you to add that new Enum.
So,
If I were you, I would think to change Stat from Enum to string, so whenever a new Stat comes, neither you need to change anything nor consumers of your wrapper, would not have to wait.

Categories