Skip to content

Instantly share code, notes, and snippets.

@trbngr
Created August 26, 2012 09:54
Show Gist options
  • Save trbngr/3476723 to your computer and use it in GitHub Desktop.
Save trbngr/3476723 to your computer and use it in GitHub Desktop.
Demonstrating how to skip fields that aren't decorated with a certain attribute using json.net.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using GuessWho;
using NUnit.Framework;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace ConsoleApplication1
{
[TestFixture]
public class ApiResourceSerializationTests
{
#region Setup/Teardown
[SetUp]
public void Setup()
{
var generator = new NameGenerator();
GeneratedName name = generator.NextName();
_person = new Person
{
Id = Guid.NewGuid(),
FirstName = name.GivenName,
LastName = name.Surname
};
for (int i = 0; i < 2; i++)
{
name = generator.NextName();
_person.Contacts.Add(new Contact
{
Id = Guid.NewGuid(),
FirstName = name.GivenName,
LastName = name.Surname
});
}
_serializerSettings = new JsonSerializerSettings {ContractResolver = new MyContractResolver()};
}
#endregion
private Person _person;
private JsonSerializerSettings _serializerSettings;
[Test]
public void will_only_serialize_api_resource_properties()
{
string json = JsonConvert.SerializeObject(_person, Formatting.Indented, _serializerSettings);
JObject obj = JObject.Parse(json);
Console.Out.WriteLine(json);
Assert.That(obj["Id"], Is.Null);
Assert.That(obj["first_name"], Is.Not.Null.And.InstanceOf<JValue>());
Assert.That(obj["LastName"], Is.Not.Null.And.InstanceOf<JValue>());
JToken contacts = obj["Contacts"];
Assert.That(contacts, Is.Not.Null.And.InstanceOf<JArray>());
var array = (JArray) contacts;
Assert.That(array[0]["Id"], Is.Null);
Assert.That(array[0]["FirstName"], Is.Not.Null.And.InstanceOf<JValue>());
Assert.That(array[0]["LastName"], Is.Not.Null.And.InstanceOf<JValue>());
Assert.That(array[1]["Id"], Is.Null);
Assert.That(array[1]["FirstName"], Is.Not.Null.And.InstanceOf<JValue>());
Assert.That(array[1]["LastName"], Is.Not.Null.And.InstanceOf<JValue>());
}
}
public class MyContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
var attribute = member.GetCustomAttribute<ApiResourcePropertyAttribute>();
if (string.IsNullOrWhiteSpace(attribute.Name))
return property;
property.PropertyName = attribute.Name;
return property;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var members = base.GetSerializableMembers(objectType);
return members.Where(p => p.GetCustomAttributes<ApiResourcePropertyAttribute>(false).Any()).ToList();
}
}
[DataContract]
public class Person
{
public Person()
{
Contacts = new List<Contact>();
}
[DataMember]
public Guid Id { get; set; }
[DataMember, ApiResourceProperty(Name = "first_name")]
public string FirstName { get; set; }
[DataMember, ApiResourceProperty]
public string LastName { get; set; }
[DataMember, ApiResourceProperty]
public List<Contact> Contacts { get; set; }
}
[DataContract]
public class Contact
{
[DataMember]
public Guid Id { get; set; }
[DataMember, ApiResourceProperty]
public string FirstName { get; set; }
[DataMember, ApiResourceProperty]
public string LastName { get; set; }
}
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class ApiResourcePropertyAttribute : Attribute
{
public string Name { get; set; }
}
}
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="GuessWho.Top1000" version="1.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="4.5.8" targetFramework="net45" />
<package id="NUnit" version="2.6.1" targetFramework="net45" />
</packages>
@trbngr
Copy link
Author

trbngr commented Aug 26, 2012

Switched to a ContractResolver. With the exception of the reflection hack in MyContractResolver.SelectName, it's much cleaner than the JsonConverter version

@trbngr
Copy link
Author

trbngr commented Aug 26, 2012

Discovered a new overload and got rid of the reflection hack. :)

@trbngr
Copy link
Author

trbngr commented Aug 26, 2012

Ditched the ApiResourceAttribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment