17

Does Json.net have any way to specify only the properties you want to be serialized? or alternatively serialize certain properties based on binding flags like Declared Only?

Right now I am using JObject.FromObject(MainObj.SubObj); to get all properties of SubObj which is an instance of a class that obeys the ISubObject interface:

public interface ISubObject
{

}

public class ParentSubObject : ISubObject
{
    public string A { get; set; }
}


public class SubObjectWithOnlyDeclared : ParentSubObject
{
    [JsonInclude] // This is fake, but what I am wishing existed
    public string B { get; set; }

    [JsonInclude] // This is fake, but what I am wishing existed
    public string C { get; set; }
}

public class NormalSubObject: ParentSubObject
{
    public string B { get; set; }
}

If MainObj.SubObj was a NormalSubObject it would serailize both A and B but if it was SubObjectWithOnlyDeclared it would serailize only B and C and ignore the parent property

CuriousDeveloper
  • 849
  • 2
  • 8
  • 27

4 Answers4

50

Rather then having to use [JsonIgnore] on every attribtue you don't want to serialise as suggested in another answer.

If you just want to specify properties to serialise, you can do this, using [JsonObject(MemberSerialization.OptIn)] and [JsonProperty] attributes, like so:

using Newtonsoft.Json;
...
[JsonObject(MemberSerialization.OptIn)]
public class Class1
{
    [JsonProperty]
    public string Property1 { set; get; }
    public string Property2 { set; get; }
}

Here only Property1 would be serialised.

Alfie
  • 1,903
  • 4
  • 21
  • 32
17

You can write a custom ContractResolver like below

public class IgnoreParentPropertiesResolver : DefaultContractResolver
{
    bool IgnoreBase = false;
    public IgnoreParentPropertiesResolver(bool ignoreBase)
    {
        IgnoreBase = ignoreBase;
    }
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        var allProps = base.CreateProperties(type, memberSerialization);
        if (!IgnoreBase) return allProps;

        //Choose the properties you want to serialize/deserialize
        var props = type.GetProperties(~BindingFlags.FlattenHierarchy); 

        return allProps.Where(p => props.Any(a => a.Name == p.PropertyName)).ToList();
    }
}

Now you can use it in your serialization process as:

var settings = new JsonSerializerSettings() { 
                      ContractResolver = new IgnoreParentPropertiesResolver(true) 
               };
var json1 = JsonConvert.SerializeObject(new SubObjectWithOnlyDeclared(),settings );
Eser
  • 12,346
  • 1
  • 22
  • 32
3

Not sure why @Eser chose to write the answer as comment to your question as opposed to an actual answer... anyway, they're correct.

Apply the [JsonIgnore] attribute to any property that you want to ignore.

Aydin
  • 15,016
  • 4
  • 32
  • 42
  • 2
    This isnt an acceptable answer though, I would need to conditionally ignore `public string A { get; set; }` because in one scenario I dont want it ignored, and in another I do. – CuriousDeveloper Jun 21 '18 at 18:15
3

If you have a property on your object that is null or the default value, you can let json.net ignore it and NOT serialize it by:

var settings = new JsonSerializerSettings 
{
    DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore
};

JsonConvert.SerializeObject(myObject, settings);

EDIT:

Or global default setting, do this once:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings 
{
    DefaultValueHandling = DefaultValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore
};
Atif Rehman
  • 417
  • 6
  • 6