In my code I want to use ShouldDeserialize method to make my response more cleaner, but ShouldDeserialize{Property} method is not visible for deserialize method. In below code ShouldSerializeItems predicate works.
public class ItemsContainer
{
public string Id { get; set; }
[JsonProperty]
public IEnumerable<Item> Items{ get; set; }
//Working
public bool ShouldSerializeItems()
{
return !Items.All(x =>
string.IsNullOrEmpty(x.ItemName) && string.IsNullOrEmpty(x.ItemId));
}
// Not working
public bool ShouldDeserializeItems()
{
return !Items.All(x =>
string.IsNullOrEmpty(x.ItemName) && string.IsNullOrEmpty(x.ItemId));
}
}
And call deserialize:
JsonConvert.DeserializeObject<ItemsContainer>(json);
In newtonsoft documentation both serialize and deserialize predicate are documented:
https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_ShouldDeserialize.htm
https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_ShouldSerialize.htm
Checking for a property named named ShouldDeserialize*() and automatically calling it was never implemented by Json.NET. See: Conditional serialization/deserialization of object properties with json.net. The infrastructure is there, so you could do it yourself by implementing a custom contract resolver that overrides DefaultContractResolver.CreateProperty() and sets JsonProperty.ShouldDeserialize.
That being said, it appears that your method ShouldDeserializeItems() assumes that the Items have already been deserialized, then filters them out based on some custom logic. Json.NET's JsonProperty.ShouldDeserialize predicate is called before deserialization, not after. When it returns true the JSON property is skipped with no ability to examine the contents, and thus cannot be used here.
Instead, you should use an [OnDeserialized] callback to clear out unwanted items after deserialization:
[System.Runtime.Serialization.OnDeserialized]
private void OnDeserializedMethod(System.Runtime.Serialization.StreamingContext context)
{
if (Items != null && Items.All(x =>
string.IsNullOrEmpty(x.ItemName) && string.IsNullOrEmpty(x.ItemId)))
Items = new List<Item>();
}
But when you are about to deserialize the Items property of the ItemContainer there is likely nothing in the Items property yet. You may not need this predicate because if the ShouldSerialize is working correctly you will never have junk data to deserialize.
Related
I have a Serializer/Deserializer that use a references PreserveReferencesHandling = PreserveReferencesHandling.All.
The issue, is that I have circular references.
Here is a very simple example.
class Node
{
public Node(object value)
{
Value = value;
}
public object Value { get; set; }
public Node Left { get; set; }
public Node Right { get; set; }
}
My test scenario is:
var obj = new Node("o")
{
Left = new Node("oL"),
Right = new Node("oR")
};
obj.Right.Right = obj; // Circular reference!
When I deserialize, i have the following IReferenceResolver
private class InternalReferenceResolver : IReferenceResolver
{
private readonly Deserializer _par;
public InternalReferenceResolver(Deserializer par)
{
_par = par;
}
public object ResolveReference(object context, string reference)
{
object refObject;
if (!_par._processed.TryGetValue(reference, out refObject))
{
refObject = _par.DeserializeObject(reference);
}
return refObject;
}
public string GetReference(object context, object value)
{
throw new NotSupportedException("Only for Serialization");
}
public bool IsReferenced(object context, object value)
{
return false;
}
public void AddReference(object context, string reference, object value)
{
_par._processed.Add(reference, value);
}
}
As you can see, when JSON.NET inform me of a new ref->object (via AddReference()) I add it to a dictionary.
When JSON.NET request an object for a specific reference (via ResolveReference()) I recurse, and deserialize that reference.
The issue is, JSON.NET calls ResolveReference() for each of the object references, before it calls it's AddReference().
I would expect the flow of Deserialization to be:
Identify Object Type
Construct the object
AddReference(id, newObj)
Resolve References + Populate Properties
What I see happens is:
Identify Object Type
Resolve References
Construct the object
AddReference(id, newObj)
Populate Properties
My Questions:
Why is it made the latter, am i missing something with my suggested flow?
how can I overcome this issue, having a "Bare" object just for referencing and only then actually resolve the references ?
The Two-Phase deserialization you are seeing is arises because your Node class only has a parameterized constructor. As explained in Issue with serializing/deserializing object graph with self-referencing objects in combination with JSON constructor. #715:
JamesNK commented on Nov 28, 2015
Non-default constructors and preserving references don't work well together because the child values of a type have to be deserialized before the parent is created, so the reference resolves to null.
Thus, since Value is a mutable property anyway, you should add a parameterless constructor to Node:
class Node
{
public Node() : this(null) { }
public Node(object value)
{
Value = value;
}
// Remainder unchanged.
}
It can be non-public if you mark it with [JsonConstructor] or deserialize using the setting ConstructorHandling.AllowNonPublicDefaultConstructor. And if Value were immutable, you would need to make it privately settable and mark it with [JsonProperty]
[JsonProperty]
public object Value { get; private set; }
(Data contract attributes can be used in place of Json.NET attributes if you prefer.)
Notes:
Since your question lacks a complete and verifiable example, your code might encounter other problems that aren't fixed by adding a parameterless constructor.
For a related question, see Usage of non-default constructor breaks order of deserialization in Json.net.
For a related issue, see PreserveReferencesHandling.Objects deserialize does not work with non-default constructor #678.
Another thing, can I tell Json.NET to only handle the constructor parameters and leave the rest... ?
Not according to Issue 715. Since a JSON object is an unordered set of name/value pairs, Json.NET needs to parse the entire object to ensure it has loaded all the constructor parameters. As it is a single-pass serializer the non-constructor parameters will get loaded into... something... before the object can be constructed. Json.NET has chosen to deserialize them in one step to the final target member type rather than to an intermediate JToken and later the final member type. This can be see in JsonSerializerInternalReader.ResolvePropertyAndCreatorValues().
Well, I Found a solution for my problem:
The first Deserialization i perform, i use a custom IContractResolver that exclude all properties that are not relevant to the constructor...
at the second pass, I use Populate and use the default IContractResolver
private class InternalOnlyCtorContractResolver : IContractResolver
{
private readonly IContractResolver _base;
public InternalOnlyCtorContractResolver(IContractResolver _base)
{
this._base = _base;
}
public JsonContract ResolveContract(Type type)
{
var contract = _base.ResolveContract(type);
var objectContract = contract as JsonObjectContract;
if (objectContract != null)
{
var creatorParameters = new HashSet<string>(objectContract.CreatorParameters.Select(p => p.PropertyName));
var irrelevantProperties = objectContract.Properties
.Where(p => !creatorParameters.Contains(p.PropertyName))
.ToArray();
foreach (var irrelevantProperty in irrelevantProperties)
{
objectContract.Properties.Remove(irrelevantProperty);
}
//TODO Can be optimized better
}
return contract;
}
}
If for some reason, the Circular Reference is needed by the Constructor,
It still cause a loop, but it is kinda impossible to create without having a second constructor anyway.
I am getting a big nested json object from an external api. I want to make sure all fields are populated in that json object. Is there any libray available to do that? Newtonsoft.Json has JToken class which checks if the Json's schema is valid or not but i don't find any method to check if all the fields inside json object are filled.
Scenario : I am building an api which gathers information about a person or entity. there are numerous sources of information. I need to continue searching for the data until the required object is full. So first call goes to api1, gets some data, checks if object is full. If object is not full then goes to api2 and so on. So the call returns after the object is full. One key point is that the required object schema is not static.
I could deserialize it to a POCO and loop through each nested object but i am looking for a better solution.
Any suggestion is highly appreciated.
If I understood you correctly, you have some complex JSON object, with a set of required and not-required properties.
I see here three solutions:
You've already mentioned JSON schema validation. Here is one of the implementations: Json.NET Schema.
Create a POCO object and mark all properties with corresponding Required/Not-Required attributes. In this case, you'll get exceptions if a json-string doesn't contain any mandatory data. For example, how it's done in terms of Json.NET's JsonPropertyAttribute:
[JsonObject]
public class PocoObject
{
[JsonProperty("$schema", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)]
public string Schema { get; set; }
[JsonProperty("name", Required = Required.Always)]
public string Name { get; set; }
[JsonProperty("properties", Required = Required.Always)]
public MorePropertiesObject Properties { get; set; }
}
As a bonus, you can add your custom attributes, methods, converters, etc
Deserialize raw json into a Dictionary-like structure and validate it with your own hands-written validator. Something like:
try
{
var jo = JObject.Parse(jsonString);
Contract.Assert(!string.IsNullOrEmpty(jo["root"]["prop1"].ToString()));
Contract.Assert(!string.IsNullOrEmpty(jo["root"]["prop2"].ToString()));
}
catch (JsonReaderException) { }
catch (JsonSerializationException) { }
Provided code samples are for mentioned by you Newtonsoft.Json
If you have a JSON string and simply want to check whether any property value or array item are null, you can parse to a JToken, recursively descend the JToken hierarchy with JContainer.DescendantsAndSelf(), and check each JValue for being null using the following extension method:
public static partial class JsonExtensions
{
public static bool AnyNull(this JToken rootNode)
{
if (rootNode == null)
return true;
// You might consider using some of the other checks from JsonExtensions.IsNullOrEmpty()
// from https://stackoverflow.com/questions/24066400/checking-for-empty-null-jtoken-in-a-jobject
return rootNode.DescendantsAndSelf()
.OfType<JValue>()
.Any(n => n.Type == JTokenType.Null);
}
public static IEnumerable<JToken> DescendantsAndSelf(this JToken rootNode)
{
if (rootNode == null)
return Enumerable.Empty<JToken>();
var container = rootNode as JContainer;
if (container != null)
return container.DescendantsAndSelf();
else
return new[] { rootNode };
}
}
And then do:
var root = JToken.Parse(jsonString);
var anyNull = root.AnyNull();
If you just want to check for null property values (i.e. null values in an array are OK) you can use the following extension method:
public static partial class JsonExtensions
{
public static bool AnyNullPropertyValues(this JToken rootNode)
{
if (rootNode == null)
return true;
return rootNode.DescendantsAndSelf()
.OfType<JProperty>()
.Any(p => p.Value == null || p.Value.Type == JTokenType.Null);
}
}
(It isn't entirely clear from your question which you want.)
Sample .Net fiddle.
My question is similar to this question - JSON.NET deserialize a specific property
. Except I want to deserialize the whole object but also use a custom method to deserialize a specific property in the class. The way I'm doing it right now is deserializing the whole object, and then calling a custom method again to deserialize a specific property in that object. This works, but I don't think it is very efficient.
public class Foo
{
public int id { get; set; }
public object item { get; set; }
}
object obj = JsonConvert.DeserializeObject(json, typeof(Foo));
//This method is from the previously asked question and it works.
object item = GetFirstInstance<GenericFoo<object>>("item", json);
Foo castedFoo= (Foo)obj;
castedFoo.item = item;
How can I update this code to make it more efficient? Something like ignore item property when the first time the object is getting deserialized?
I have a class which I use the XmlSerializer with to serialize data to and from XML files.
I have several DateTime properties. In the post, Prevent timezone conversion on deserialization of DateTime value the answer correctly removes timezone offsets from DateTime properties.
However, I have a property which is a list of DateTime objects that I can't remove the timezones from.
[XmlElement]
public List<DateTime> Times {get; set;}
I have tired something like this, but the value is always null and none of the data is correctly serialized to the list property.
[XmlIgnore]
public List<DateTime> Times {get; set;}
[XmlElement(ElementName = "Times")]
public List<string> TimesString
{
get
{
return Times.ForEach(fe => RemoveTimeZone(fe));
}
set
{
foreach(var v in value)
{
Times.Add(ConvertToDate(v));
}
}
}
The value property is always empty and both list properties are always empty.
My goal is to not create a new class, but to somehow bind directly to my list properties.
Your TimesString property is a proxy collection property, i.e. a property that gets or sets an underlying collection, transforming its members in the process. The simplest way to make such a proxy collection work correctly with XmlSerializer is to make it be an array rather than a list, in your case a string []:
[XmlIgnore]
public List<DateTime> Times { get; set; }
[XmlElement(ElementName = "Times")]
public string [] TimesString
{
get
{
return Times == null ? null : Times.Select(t => RemoveTimeZone(t)).ToArray();
}
set
{
if (value == null)
return;
(Times = Times ?? new List<DateTime>(value.Length)).AddRange(value.Select(s => ConvertToDate(s)));
}
}
string [] works while List<string> does not because XmlSerializer deserializes a property referring to a class implementing IList<T> in the following way:
It calls the getter to get the list. If null, it allocates a list and sets it via the setter. It holds onto the list in some local variable while populating it.
It deserializes each list element, and adds it to the list it is holding.
And that's it. It never calls the containing class's list property setter afterwards.
However, since an array is basically a read-only collection and so cannot be added to once allocated, it cannot be set back until completely populated. This is what XmlSerializer does, which allows proxy array properties to deserialized successfully.
For more, see Cannot deserialize XML into a list using XML Deserializer or XML Deserialization of collection property with code defaults.
I have a list of objects that implement a common interface. If I try to simply serialize it I get a nice exception that tells me that the serializer cannot serialize interfaces:
private readonly ObservableCollection<ICanHasInterface> children = new ObservableCollection<ICanHasInterface>();
public ObservableCollection<ICanHasInterface> Children
{
get { return children; }
}
=> "Cannot serialize member ... of type ... because it is an interface"
Apparently asking the serializer to get the type of the objects and mark the XmlElement with the attribute xsi:type (which is done if an object inherits from another class) is too much.
So because I do not want to implement IXmlSerializable, I thought up a workaround which looked promising initially:
private readonly ObservableCollection<ICanHasInterface> children = new ObservableCollection<ICanHasInterface>();
[XmlIgnore()]
public ObservableCollection<ICanHasInterface> Children
{
get { return children; }
}
[XmlElement("Child")]
public List<object> ChildrenSerialized
{
get
{
return new List<object>(Children);
}
set
{
Children.Clear();
foreach (var child in value)
{
if (child is ICanHasInterface) AddChild(child as ICanHasInterface);
}
}
}
With this at least the serialisation works just fine (Note: Either specify XmlInclude attributes for the types that can be in the original list or hand over an array of types in the constructor of the serializer), however if the object is deserialized the Children collection ends up empty because the set block is never reached during deserialization, I am quite clueless as to why this is; any ideas?
On deserialization the serializer uses your property getter to get the collection instance and then calls Add() on it for each item. It does not call your property setter. Something like this:
YourClass c = new YourClass();
c.ChildrenSerialized.Add(ReadValue());
...
In order to keep the collections synchronized you'd need to customize the Add() behavior of the collection you return from the property getter.
A better option is to change the ChildrenSerialized property to use an object[]. For arrays, the serializer reads the value into an array and then calls your property setter with the value.