Justin Helgerson
Justin Helgerson

Reputation: 25551

Disallow serialization, allow deserialization on property

I have a very simple C# class:

[Serializable]
[JsonObject]
public class ObjectBase {
    public string Id { get; set; }
    public string CreatedById { get; set; }
    public DateTime CreatedDate { get; set; }
    public string LastModifiedById { get; set; }
    public DateTime LastModifiedDate { get; set; }
}

The properties Id, CreatedDate and LastModifiedDate are values that I don't want to be serialized (I'm integrating with a third party API, and those values can never be updated).

However, I would like those properties to be populated with data when I have JSON that I'm deserializing.

I tried using [JsonIgnore], but that results in the property being skipped during deserialization. Is it possible to use the properties in this manner?

Edit:

I am using inheritance already as all of my objects require the same base properties. I always de/serialize into the child class (e.g. Account):

[Serializable]
[JsonObject]
public class Account : ObjectBase {
    public string AccountNumber { get; set; }
    public string ParentId { get; set; }
}

As an example, I might have an instance of the Account object and the Id and CreatedDate properties could have a value. When I serialize that object into JSON, I don't want those properties to be included. However, when I have JSON and am deserializing, I want those properties to get a value.

Upvotes: 1

Views: 316

Answers (2)

Brian Rogers
Brian Rogers

Reputation: 129827

One way to exclude certain properties from serialization without having to modify your class structure is to create a custom ContractResolver like this:

class CustomResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
        if (typeof(ObjectBase).IsAssignableFrom(type))
        {
            string[] excludeThese = new string[] { "Id", "CreatedDate", "LastModifiedDate" };
            props = props.Where(p => !excludeThese.Contains(p.PropertyName)).ToList();
        }
        return props;
    }
}

When you serialize, just add the resolver to the serializer settings:

Account account = new Account
{
    Id = "100",
    CreatedById = "2",
    CreatedDate = new DateTime(2014, 3, 12, 14, 52, 18, DateTimeKind.Utc),
    LastModifiedById = "3",
    LastModifiedDate = new DateTime(2014, 3, 17, 16, 3, 34, DateTimeKind.Utc),
    AccountNumber = "1234567",
    ParentId = "99"
};

JsonSerializerSettings settings = new JsonSerializerSettings()
{
    ContractResolver = new CustomResolver(),
    Formatting = Formatting.Indented
};

string json = JsonConvert.SerializeObject(account, settings);
Console.WriteLine(json);

Output:

{
  "AccountNumber": "1234567",
  "ParentId": "99",
  "CreatedById": "2",
  "LastModifiedById": "3"
}

Another Approach

If you don't like the resolver approach, another alternative is to add boolean ShouldSerializeX methods to your class where X is replaced with names of the properties that you want to exclude:

[Serializable]
[JsonObject]
public class ObjectBase
{
    public string Id { get; set; }
    public string CreatedById { get; set; }
    public DateTime CreatedDate { get; set; }
    public string LastModifiedById { get; set; }
    public DateTime LastModifiedDate { get; set; }

    public bool ShouldSerializeId()
    {
        return false;
    }

    public bool ShouldSerializeCreatedDate()
    {
        return false;
    }

    public bool ShouldSerializeLastModifiedDate()
    {
        return false;
    }
}

Upvotes: 2

Haney
Haney

Reputation: 34922

Object inheritance is the key. You want to serialize a subset of properties/fields, and deserialize the full set. So, make the full set derive from the subset and use them appropriately in your serialization and deserialization.

Serialize this class:

[Serializable]
[JsonObject]
public class ObjectBase
{
    public string CreatedById { get; set; }
    public string LastModifiedById { get; set; }
}

Deserialize this class:

[Serializable]
[JsonObject]
public class ObjectDeserializationBase : ObjectBase
{
    public string Id { get; set; }
    public DateTime CreatedDate { get; set; }
    public DateTime LastModifiedDate { get; set; }
}

Upvotes: 0

Related Questions