Echilon
Echilon

Reputation: 10254

Excluding properties on domain model objects from JSON

I'm using Newtonsoft JSON to serialize a graph of objects which are defined in a satellite assembly. I have a circular reference which is causing the recursion limit in JSON to be exceeded and adding extra bloat to an already data heavy POST.

The documented way would be to add a JsonIgnore attribute to the property on my data object, but that would require a Newtonsoft.Json reference in my domain project. Is there any other way of excluding a property from serialization?

Upvotes: 2

Views: 331

Answers (3)

smoksnes
smoksnes

Reputation: 10851

Alternative 1

You should be able to use [DataContract] together with [DataMember].

[DataContract]
public class MyDomainModel
{
    [DataMember]
    public string PublicString { get; set; }

    public string HiddenString { get; set; }

    public MyDomainModel InfiniteReference { get; set; }
}

It requires a reference to System.Runtime.Serialization.

Example:

[HttpGet]
public MyDomainModel GetModels()
{
        var model = new MyDomainModel
        {
            HiddenString = "Hidden",
            PublicString = "Public",
        };
        model.InfiniteReference = model;
        return model;
 }

Output:

{
"publicString": "Public"
}

Alternative 2

I have a circular reference [...]

You could use ReferenceLoopHandling, which simply cuts the circular reference. But this might not be want you want, when you mentioned other extra bloat.

config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

Upvotes: 3

Electric Sheep
Electric Sheep

Reputation: 4330

You can apply the [IgnoreDataMember] attribute on the model properties, which references System.Runtime.Serialization. All other properties will be serialized by default.

e.g.

public class MyViewModel
{
    public string SerializedProperty { get; set; }

    [IgnoreDataMember]
    public string IgnoredProperty { get; set; }
}

Upvotes: 0

J. Steen
J. Steen

Reputation: 15578

Had a similar issue. I solved it in an entirely overwrought and overengineered fashion with a custom attribute and contract-resolver, when serializing, so I didn't need to reference any external libs (with the exception of System) in my model.

Declare your own attribute, such as

[AttributeUsage(AttributeTargets.Property)]
public sealed class IgnoreMeAttribute : Attribute
{
}

Decorate your model

[IgnoreMe]
public string IgnoreMePlease { get; set; }

Add a

public class ShouldSerializeContractResolver : DefaultContractResolver
{
    public static readonly ShouldSerializeContractResolver Instance = new ShouldSerializeContractResolver();

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        if (property.AttributeProvider.GetAttributes(typeof (IgnoreMeAttribute), false).Any())
            property.ShouldSerialize = instance => false;

        return property;
    }
}

and use it

var result = JsonConvert.SerializeObject(value, Formatting.None, new JsonSerializerSettings { ContractResolver = ShouldSerializeContractResolver.Instance });

Upvotes: 0

Related Questions