简体   繁体   中英

How can I override the JSON serialization for a property, to serialize the value as a string instead of an object?

Using.Net 4.8 I have all my entity framework classes inheriting from an AbstractBase:

public abstract class AbstractBase
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int Id { get; set; }

    public virtual DateTime CreatedTimestamp { get; set; }

    public virtual DateTime UpdatedTimestamp { get; set; }

    [Required]
    public virtual int CreatedBy { get; set; }

    [Required]
    public virtual int LastModifiedBy { get; set; }

    public virtual bool ActiveFlag { get; set; }

    [JsonIgnore]
    public virtual User CreatedByUser { get; set; }

    [JsonIgnore]
    public virtual User LastModifiedByUser { get; set; }

    public string ToActiveInactive()
    {
        return this.ActiveFlag ? "Active" : "Inactive";
    }
}

Now as you can see I am ignoring the CreatedByUser and LastModifiedByUser . What I would like to do instead is somehow replace the User object with a property called FullName which the User object can provide like

User test = new User();
test.GetFullName();

My User object already has this so my question is there a way to do this so I do not have to write more implementation of the same logic every time I want to serialize an entity class?

You can create a custom JsonConverter<T> like the one shown in the Newtonsoft documentation to serialize your User class as a string:

public class UserConverter : JsonConverter<User>
{
    public override void WriteJson(JsonWriter writer, User value, JsonSerializer serializer)
    {
        writer.WriteValue(value.GetFullName());
    }

    public override User ReadJson(JsonReader reader, Type objectType, User existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var fullName = serializer.Deserialize<string>(reader);
        // Or construct a User and return it, if you can do so from the fullName.
        throw new NotImplementedException();
    }
}

Note that your question does not provide enough information for me to write the ReadJson() method. If you need to support deserialization, you will need to fully implement this method by constructing a User from the fullName string.

Now, to use the converter, you have several options:

  1. If you only want the User properties of AbstractBase to be serialized as strings, apply the converter to the User properties using JsonConverterAttribute as follows:

     public abstract class AbstractBase { [JsonConverter(typeof(UserConverter))] public virtual User CreatedByUser { get; set; } [JsonConverter(typeof(UserConverter))] public virtual User LastModifiedByUser { get; set; } // Remaining properties and methods unchanged
  2. If you want all instances of User of to be serialized as a string, you can apply it directly to User as follows:

     [JsonConverter(typeof(UserConverter))] public class User { // Properties and methods unchanged
  3. Or, you could add it to your global JsonSerializerSettings.Converters . To do this in .NET Framework, see this answer to Json.net global settings by Andrei . For .NET Core 2.x see this answer to Customizing response serialization in ASP.NET Core MVC by Métoule .

  4. .NET Core 3.x and later use a difference serializer, , so you will have to use a different approach in that version, or revert back to using Json.NET as shown in Where did IMvcBuilder AddJsonOptions go in.Net Core 3.0? .

Demo fiddle here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM