Backwards-compatible XML Deserialization - c#

I am deserializing an XML configuration file by performing the following:
XmlSerializer deserializer = new XmlSerializer(typeof(MyType));
using (TextReader textReader = new StreamReader(fn))
{
return (MyType)deserializer.Deserialize(textReader);
}
Then I have a simple method to check if the XML configuration file matches the values in the current UI.
if ((config.Description == null || config.Description != this.Description.Text)
|| (config.Location == null || config.Location != this.Location.Text)
|| (config.Provider == null || config.Provider != this.Provider.Text))
So if I have an older configuration file containing just config.Description, then config.Location and config.Provider will be null when the XML file is deserialized. How can I just simplify this so that config.Location is set to the default value for the typed property instead (in this case the strings would be set to zero-length strings), allowing me to drop all the null checks? For example:
if (config.Description != this.Description.Text
|| config.Location != this.Location.Text
|| config.Provider != this.Provider.Text)
I know one option is to create an instance besides the deserialized instance and loop through all properties using Reflection (or some other similar approach) but I was hoping there was a built-in way to assign default values to properties that weren't deserialized. I'm mostly wondering if this is the correct approach, as I'm trying to reduce unnecessary bloat when dealing with a larger amount of settings.
I've searched for duplicates of this problem, but most people are trying to deserialize an instance into itself and using the serialization event to control that behavior.

The XmlSerializer requires a parameterless constructor. However you can use any of the initialization techniques as shown below:
public class MyType
{
private string _description = default(string); // Note the default is NULL, not "" for a string
// However, why not determine the default yourself?
private string _location = "";
private string _provider;
public MyType()
{
// Or use the constructor to set the defaults
_provider = string.Empty;
}
public string Description
{
get { return _description; }
set { _description = value; }
}
}

"..I was hoping there was a built-in way to assign default values to properties that weren't deserialized.."
You can set default values in the class constructor.

Related

Is there any difference between the null conditional operator and a dedicated null check?

For instance:
I have an instance that may or may not be null.
I want to get the value of one of its bool members.
I wrote some awful code like this:
var someVar = (someInstance != null) ? someInstance.boolValue : false;
ReSharper suggested two other ways to do the same:
var someVar = someInstance?.boolValue ?? false;
var someVar = (someInstance != null) && someInstance.boolValue;
Is there any technical reason to prefer either of them, or do they end up doing the exact same?
Alternative approach is not to return null, but create a "Default" instance of the type. Can be good fit in the scenario where you have default values
public class MyClass
{
public static readonly MyClass Default = new MyClass(false);
public bool HaveSomething { get; }
public MyClass(bool haveIt) => HaveSomething = haveIt;
}
// Usage
var someThing = LoadThing(); // Never returns null
if (someThing.HaveSomething)
{
// some action
}
The goal is to check for null only once when you load or trying to create an instance, then you can remove null checks from the rest of the application

How to Check if Json object has all values filled

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.

Generic change tracking class improvements

I am developing a generic reflection class for change tracking. What I have works just fine for all classes that I put it through. I am getting ready to move it out as part of a tool to the entire group. I am interested in improving this a bit more before I role it out to everyone. It is called from methods that have error handling in place so that part is not an issue. Also this works perfectly in our logic the way we flatten objects for change tracking, but am I missing something that could be an issue even though it works perfectly for the usual situations.
public class ChangeTracker
{
public static string GetChangesString<T,S>(T original, T current, S dto, string[] exluded)
{
StringBuilder sb = new StringBuilder();
PropertyInfo[] names = typeof(S).GetProperties();
string displayName = string.Empty;
foreach (PropertyInfo item in names)
{
if (exluded.Contains(item.Name)) continue;
//method that sets display name to either the property name or the display attribute if present
displayName = GetDisplayName(item);
object propA = original.GetType().GetProperty(item.Name).GetValue(original, null);
object propB = current.GetType().GetProperty(item.Name).GetValue(original, null);
if (propA == null && propB == null) continue;
if (propA == null && propB != null)
{
//appendline for value added
}
else if (propB == null && propA != null)
{
//appendline for value removed
}
else if (propA.ToString() != propB.ToString())
{
//appendline for value changed
}
}
return sb.ToString();
}
private static string GetDisplayName(PropertyInfo prop)
{
string display = string.Empty;
//Check for displayattribute and set correct name
return display;
}
}
Specifically this is my question.
Is there a better way I can do the propA and propB setting to improve performance? It works on one object changing and I have tested it up to 103 properties with no performance issues, but I try to avoid stuff like this when I can.
Thanks
Jimmy
You can use Reflection + Expression Trees combination to build getter Func's. And I recommned to build this expressions on application start and cache them(per type), that should drastically improve performance. But this will greatly increase you code base size=)

How are you supposed to write attributes with null values in XML

Im using linq to xml to write out a little config file for an application and was a little surprised to discover XAttributes dont accept null as their value - they throw an exception instead.
Null is a perfectly valid value for many of the properties in my config and I dont want to have to null check attributes everywhere:
var attribute = _element.Attribute(attribute);
var value = attribute == null ? null : attribute.Value;
A further reason I dont want to write code like this is that it will make it easier to mis type names of things - eg if an attribute is spelled wrong it will just act like an attribute that exists but has a null value rather than throwing an exception.
The solution I have at the moment is as follows but it seems a little bit ugly + like something you shouldnt need to do.
I've knocked up a little class to make it a bit easier to write + read xml and am using a string containing just the null character to signal a null string.
I've omitted everything except the indexer for brevity:
public class XContainerWrapper
{
private readonly XElement _element;
public XContainerWrapper(XElement xElement)
{
_element = xElement;
}
public string this[string attribute]
{
get
{
var value = _element.Attribute(attribute).Value;
return value == "\0" ? null : value;
}
set
{
var valueToWrite = value ?? "\0";
_element.Add(new XAttribute(attribute, valueToWrite));
}
}
}
You can write your own extension method instead of XAttribute Value getter:
public static class XmlExtensions {
public static string SafeValue(this XAttribute attribute) {
var value = attribute == null ? null : attribute.Value;
return value;
}
}
Then you can use
XAttribute a = null;
var value = a.SafeValue();

Empty object check

Is there a way to know if all the properties in an object are empty. My object represents fields from database and I want to know if a particular record is present or not. NULL doesnt seem to work.
Have you tried checking against DBNull.Value
You can use reflection:
public static bool IsEmptyEntity<T>(T obj)
{
foreach (var property in typeof(T).GetProperties())
if (property.GetValue(obj, null) != null)
return false;
return true;
}
Usage:
public class MyTestEntity
{
public string Str { get; set; }
public int? Int { get; set; }
}
MyTestEntity test = new MyTestEntity();
var empty = IsEmptyEntity(test); //returns true
If the record is not present, then why would you have an object to represent it?
If your object represents fields from database, then it's probably a collection. If so, you can most likely use an extension method like myCollection.Any() to see if there are any objects inside the collection. Is that what you are asking for?
A lot of languages use a method or property called IsEmpty for this kind of check. During the hydration phase of the object set a boolean flag that specifies if the object is empty or not. Then you can simply use the property or method elsewhere to check for empty objects.
ie
During hydration
bool _isEmpty = false;
if( prop1 is empty && prop2 is empty )
{
_isEmpty = true;
}
else
{
_isEmpty = false;
}
Then use an IsEmpty property
IsEmpty
{
get { return _isEmpty; }
}
I've found occasions where using just a check with DBNull isn't enough. Maybe not the purest approach but a temporary check as a string seems to do the trick. Like so:
if ((DBNull.Value != field) &&
(!string.IsNullOrWhiteSpace(field.ToString())))

Categories

Resources