Skip to content

Commit

Permalink
Ignore unmapped properties in YAML
Browse files Browse the repository at this point in the history
  • Loading branch information
nickbabcock authored and aaubry committed Feb 28, 2014
1 parent 7d9718e commit acdde89
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 11 deletions.
7 changes: 7 additions & 0 deletions YamlDotNet.Test/Serialization/SerializationTestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,13 @@ public class Simple
public string aaa { get; set; }
}

public class SimpleScratch
{
public string Scratch { get; set; }
public bool DeleteScratch { get; set; }
public IEnumerable<string> MappedScratch { get; set; }
}

public class Example
{
public bool MyFlag { get; set; }
Expand Down
47 changes: 47 additions & 0 deletions YamlDotNet.Test/Serialization/SerializationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

namespace YamlDotNet.Test.Serialization
{
Expand Down Expand Up @@ -668,5 +669,51 @@ public void TypeConverterIsUsedOnListItems()
.Should().NotBeNull()
.And.ContainSingle(c => c.Equals("[hello, world]"));
}

[Fact]
public void IgnoreExtraPropertiesIfWanted()
{
var text = Lines("aaa: hello", "bbb: world");
var des = new Deserializer(ignoreUnmatched: true);
var actual = des.Deserialize<Simple>(UsingReaderFor(text));
actual.aaa.Should().Be("hello");
}

[Fact]
public void DontIgnoreExtraPropertiesIfWanted()
{
var text = Lines("aaa: hello", "bbb: world");
var des = new Deserializer(ignoreUnmatched: false);
var actual = Record.Exception(() => des.Deserialize<Simple>(UsingReaderFor(text)));
Assert.IsType<System.Runtime.Serialization.SerializationException>(actual);
}

[Fact]
public void IgnoreExtraPropertiesIfWantedBefore()
{
var text = Lines("bbb: [200,100]", "aaa: hello");
var des = new Deserializer(ignoreUnmatched: true);
var actual = des.Deserialize<Simple>(UsingReaderFor(text));
actual.aaa.Should().Be("hello");
}

[Fact]
public void IgnoreExtraPropertiesIfWantedNamingScheme()
{
var text = Lines(
"scratch: 'scratcher'",
"deleteScratch: false",
"notScratch: 9443",
"notScratch: 192.168.1.30",
"mappedScratch:",
"- '/work/'"
);

var des = new Deserializer(namingConvention: new CamelCaseNamingConvention(), ignoreUnmatched: true);
var actual = des.Deserialize<SimpleScratch>(UsingReaderFor(text));
actual.Scratch.Should().Be("scratcher");
actual.DeleteScratch.Should().Be(false);
actual.MappedScratch.Should().ContainInOrder(new[] {"/work/"});
}
}
}
2 changes: 1 addition & 1 deletion YamlDotNet.build
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<!-- This build file requires .NET 4.0 and nant 0.91 alpha 2 or higher -->
<property name="nant.settings.currentframework" value="net-4.0"/>

<property name="version" value="3.0.0" />
<property name="version" value="3.1.0" />

<fileset id="binaries">
<include name="YamlDotNet/bin/Release/YamlDotNet.dll" />
Expand Down
11 changes: 7 additions & 4 deletions YamlDotNet/Serialization/Deserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,16 @@ public IEnumerable<IPropertyDescriptor> GetProperties(Type type, object containe
return TypeDescriptor.GetProperties(type, container);
}

public IPropertyDescriptor GetProperty(Type type, object container, string name)
public IPropertyDescriptor GetProperty(Type type, object container, string name, bool ignoreUnmatched)
{
return TypeDescriptor.GetProperty(type, container, name);
return TypeDescriptor.GetProperty(type, container, name, ignoreUnmatched);
}
}

public Deserializer(IObjectFactory objectFactory = null, INamingConvention namingConvention = null)
public Deserializer(
IObjectFactory objectFactory = null,
INamingConvention namingConvention = null,
bool ignoreUnmatched = false)
{
objectFactory = objectFactory ?? new DefaultObjectFactory();
namingConvention = namingConvention ?? new NullNamingConvention();
Expand Down Expand Up @@ -101,7 +104,7 @@ public Deserializer(IObjectFactory objectFactory = null, INamingConvention namin
NodeDeserializers.Add(new GenericCollectionNodeDeserializer(objectFactory));
NodeDeserializers.Add(new NonGenericListNodeDeserializer(objectFactory));
NodeDeserializers.Add(new EnumerableNodeDeserializer());
NodeDeserializers.Add(new ObjectNodeDeserializer(objectFactory, typeDescriptor));
NodeDeserializers.Add(new ObjectNodeDeserializer(objectFactory, typeDescriptor, ignoreUnmatched));

tagMappings = new Dictionary<string, Type>(predefinedTagMappings);
TypeResolvers = new List<INodeTypeResolver>();
Expand Down
6 changes: 5 additions & 1 deletion YamlDotNet/Serialization/ITypeInspector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ public interface ITypeInspector
/// <param name="type">The type whose properties are to be searched.</param>
/// <param name="container">The actual object of type <paramref name="type"/> whose properties are to be searched. Can be null.</param>
/// <param name="name">The name of the property.</param>
/// <param name="ignoreUnmatched">
/// Determines if an exception or null should be returned if <paramref name="name"/> can't be
/// found in <paramref name="type"/>
/// </param>
/// <returns></returns>
IPropertyDescriptor GetProperty(Type type, object container, string name);
IPropertyDescriptor GetProperty(Type type, object container, string name, bool ignoreUnmatched);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
// THE SOFTWARE.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization.Utilities;
Expand All @@ -30,11 +33,13 @@ public sealed class ObjectNodeDeserializer : INodeDeserializer
{
private readonly IObjectFactory _objectFactory;
private readonly ITypeInspector _typeDescriptor;
private readonly bool _ignoreUnmatched;

public ObjectNodeDeserializer(IObjectFactory objectFactory, ITypeInspector typeDescriptor)
public ObjectNodeDeserializer(IObjectFactory objectFactory, ITypeInspector typeDescriptor, bool ignoreUnmatched)
{
_objectFactory = objectFactory;
_typeDescriptor = typeDescriptor;
_ignoreUnmatched = ignoreUnmatched;
}

bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<EventReader, Type, object> nestedObjectDeserializer, out object value)
Expand All @@ -50,8 +55,13 @@ bool INodeDeserializer.Deserialize(EventReader reader, Type expectedType, Func<E
while (!reader.Accept<MappingEnd>())
{
var propertyName = reader.Expect<Scalar>();

var property = _typeDescriptor.GetProperty(expectedType, null, propertyName.Value);
var property = _typeDescriptor.GetProperty(expectedType, null, propertyName.Value, _ignoreUnmatched);
if (property == null)
{
reader.SkipThisAndNestedEvents();
continue;
}

var propertyValue = nestedObjectDeserializer(reader, property.Type);
var propertyValuePromise = propertyValue as IValuePromise;
if (propertyValuePromise == null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,20 @@ public abstract class TypeInspectorSkeleton : ITypeInspector
{
public abstract IEnumerable<IPropertyDescriptor> GetProperties(Type type, object container);

public IPropertyDescriptor GetProperty(Type type, object container, string name)
public IPropertyDescriptor GetProperty(Type type, object container, string name, bool ignoreUnmatched)
{
var candidates = GetProperties(type, container)
.Where(p => p.Name == name);

using(var enumerator = candidates.GetEnumerator())
{
if(!enumerator.MoveNext())
{
if (ignoreUnmatched)
{
return null;
}

throw new SerializationException(
string.Format(
CultureInfo.InvariantCulture,
Expand Down

1 comment on commit acdde89

@aaubry
Copy link
Owner

@aaubry aaubry commented on acdde89 Feb 28, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merge of pull request #88

Please sign in to comment.