1

I'm using Newtonsoft.Json to serialize values for caching and I'm wondering if there is a way to exclude executable properties in the same way that methods are excluded from serialization? Preferably a way to set it globally so I don't need to mark hundreds of properties with an attribute (that I would first have to find among many thousands of properties).

The code:

[Serializable]
public class Item
{
    public long Id { get; set; }

    public string Name { get; set; }

    public List<Image> Images { get; set; }

    public Image PrimaryImage { get { return Images[0]; } }
}

[Serializable]
public class Image
{
    public long Id { get; set; }

    public string FileName { get; set; }
}

The error:

Error getting value from 'PrimaryImage' on 'Item'.
at Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)

I'll also mention that the logic in PrimaryImage has been simplified so the solution is not to skip using the property. This seems like a pretty common use of properties so I find it strange that it does not handle it already.

Div1
  • 13
  • 2
  • You can create a `ContractResolver`: http://stackoverflow.com/questions/33258314/how-to-exclude-specific-type-from-json-serialization/33259101#33259101 The answer I provided is specific to ignoring properties of a specific type but can be modified to suit your needs. You can also set it globally which is handy. – Ric Feb 02 '16 at 11:26
  • @Ric That's a step in the right direction but do you have any suggestion how I would differentiate between the properties that are simple data containers and those that are executable? – Div1 Feb 02 '16 at 12:10
  • What do you define as executable? – Ric Feb 02 '16 at 12:10
  • @Ric It seems that the serializer has a problem with any property that is not a { get; set; } auto-implemented property so then that is my definition. Any properties with accessors defined. – Div1 Feb 02 '16 at 12:30
  • I'm sure it is easy to exclude properties that are read only/ write only too in fact here is the doc that shows the options available http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_JsonProperty.htm – Ric Feb 02 '16 at 12:32

1 Answers1

0

Try this code (serialize only get-set properties):

public static class NewtonsoftDefaultSettings
{
    public static JsonSerializerSettings CreateRelease()
    {
        return Create(Formatting.None);
    }

    public static JsonSerializerSettings CreateDebug()
    {
        return Create(Formatting.Indented);
    }

    private static JsonSerializerSettings Create(Formatting formatting)
    {
        return new JsonSerializerSettings
        {
            Formatting = formatting,
            ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
            ContractResolver = new MyContractResolver()
        };
    }
}

internal class MyContractResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        var members = base.GetSerializableMembers(objectType).Cast<PropertyInfo>().ToList();
        members.RemoveAll(x => !x.CanRead || !x.CanWrite);
        return members.Cast<MemberInfo>().ToList();
    }
}

And finally:

var str = JsonConvert.SerializeObject(value, NewtonsoftDefaultSettings.CreateDebug());
Sergey Petrov
  • 121
  • 1
  • 4
  • This excludes properties based on their return type. My problem is not what type of value is returned but rather how that value is returned. – Div1 Feb 02 '16 at 14:29
  • @Div1 you still need to provide more information regarding "how that value is returned" we can't guess unless you give more information. – Ric Feb 02 '16 at 14:35
  • Of course, sorry, I described the problem more in the comments below my question. Specifically, the serializer appears to have a problem with any property that is not a { get; set; } auto-implemented property, so I need it to exclude properties that have their accessors defined. – Div1 Feb 02 '16 at 15:49
  • Ok. I changed my code. Now only get-set properties is serialized. – Sergey Petrov Feb 03 '16 at 07:08
  • I haven't figured out exactly what is causing the problem. In my code there are multiple cases where the same type of property sometimes works and sometimes not and my quick testing could not narrow down the reason. Anyway, this solution solves my problem and it also makes the serialized values smaller leaving out unnecessary duplicate data. – Div1 Feb 03 '16 at 19:23