Newtonsoft JSON dynamic property name

Robert

Is there a way to change name of Data property during serialization, so I can reuse this class in my WEB Api.

For an example, if i am returning paged list of users, Data property should be serialized as "users", if i'm returning list of items, should be called "items", etc.

Is something like this possible:

public class PagedData
{
    [JsonProperty(PropertyName = "Set from constructor")]??
    public IEnumerable<T> Data { get; private set; }
    public int Count { get; private set; }
    public int CurrentPage { get; private set; }
    public int Offset { get; private set; }
    public int RowsPerPage { get; private set; }
    public int? PreviousPage { get; private set; }
    public int? NextPage { get; private set; }
}

EDIT:

I would like to have a control over this functionality, such as passing name to be used if possible. If my class is called UserDTO, I still want serialized property to be called Users, not UserDTOs.

Example

var usersPagedData = new PagedData("Users", params...);
Brian Rogers

You can do this with a custom ContractResolver. The resolver can look for a custom attribute which will signal that you want the name of the JSON property to be based on the class of the items in the enumerable. If the item class has another attribute on it specifying its plural name, that name will then be used for the enumerable property, otherwise the item class name itself will be pluralized and used as the enumerable property name. Below is the code you would need.

First let's define some custom attributes:

public class JsonPropertyNameBasedOnItemClassAttribute : Attribute
{
}

public class JsonPluralNameAttribute : Attribute
{
    public string PluralName { get; set; }
    public JsonPluralNameAttribute(string pluralName)
    {
        PluralName = pluralName;
    }
}

And then the resolver:

public class CustomResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty prop = base.CreateProperty(member, memberSerialization);
        if (prop.PropertyType.IsGenericType && member.GetCustomAttribute<JsonPropertyNameBasedOnItemClassAttribute>() != null)
        {
            Type itemType = prop.PropertyType.GetGenericArguments().First();
            JsonPluralNameAttribute att = itemType.GetCustomAttribute<JsonPluralNameAttribute>();
            prop.PropertyName = att != null ? att.PluralName : Pluralize(itemType.Name);
        }
        return prop;
    }

    protected string Pluralize(string name)
    {
        if (name.EndsWith("y") && !name.EndsWith("ay") && !name.EndsWith("ey") && !name.EndsWith("oy") && !name.EndsWith("uy"))
            return name.Substring(0, name.Length - 1) + "ies";

        if (name.EndsWith("s"))
            return name + "es";

        return name + "s";
    }
}

Now you can decorate the variably-named property in your PagedData<T> class with the [JsonPropertyNameBasedOnItemClass] attribute:

public class PagedData<T>
{
    [JsonPropertyNameBasedOnItemClass]
    public IEnumerable<T> Data { get; private set; }
    ...
}

And decorate your DTO classes with the [JsonPluralName] attribute:

[JsonPluralName("Users")]
public class UserDTO
{
    ...
}

[JsonPluralName("Items")]
public class ItemDTO
{
    ...
}

Finally, to serialize, create an instance of JsonSerializerSettings, set the ContractResolver property, and pass the settings to JsonConvert.SerializeObject like so:

JsonSerializerSettings settings = new JsonSerializerSettings
{
    ContractResolver = new CustomResolver()
};

string json = JsonConvert.SerializeObject(pagedData, settings);

Fiddle: https://dotnetfiddle.net/GqKBnx

If you're using Web API (looks like you are), then you can install the custom resolver into the pipeline via the Register method of the WebApiConfig class (in the App_Start folder).

JsonSerializerSettings settings = config.Formatters.JsonFormatter.SerializerSettings;
settings.ContractResolver = new CustomResolver();

Another Approach

Another possible approach uses a custom JsonConverter to handle the serialization of the PagedData class specifically instead using the more general "resolver + attributes" approach presented above. The converter approach requires that there be another property on your PagedData class which specifies the JSON name to use for the enumerable Data property. You could either pass this name in the PagedData constructor or set it separately, as long as you do it before serialization time. The converter will look for that name and use it when writing out JSON for the enumerable property.

Here is the code for the converter:

public class PagedDataConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(PagedData<>);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Type type = value.GetType();

        var bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
        string dataPropertyName = (string)type.GetProperty("DataPropertyName", bindingFlags).GetValue(value);
        if (string.IsNullOrEmpty(dataPropertyName)) 
        {
            dataPropertyName = "Data";
        }

        JObject jo = new JObject();
        jo.Add(dataPropertyName, JArray.FromObject(type.GetProperty("Data").GetValue(value)));
        foreach (PropertyInfo prop in type.GetProperties().Where(p => !p.Name.StartsWith("Data")))
        {
            jo.Add(prop.Name, new JValue(prop.GetValue(value)));
        }
        jo.WriteTo(writer);
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

To use this converter, first add a string property called DataPropertyName to your PagedData class (it can be private if you like), then add a [JsonConverter] attribute to the class to tie it to the converter:

[JsonConverter(typeof(PagedDataConverter))]
public class PagedData<T>
{
    private string DataPropertyName { get; set; }
    public IEnumerable<T> Data { get; private set; }
    ...
}

And that's it. As long as you've set the DataPropertyName property, it will be picked up by the converter on serialization.

Fiddle: https://dotnetfiddle.net/8E8fEE

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Java

Newtonsoft.Json DeserializeXmlNode changes tag name from number to "something"

From Java

.NET NewtonSoft JSON deserialize map to a different property name

From Dev

Serialize Dynamic Property Name for an Object using JSON.NET

From Dev

How to update a property of a JSON object using NewtonSoft

From Dev

How to make an anonymous types property name dynamic?

From Dev

Deserialize Dynamic JSON file C# NewtonSoft.JSON

From Dev

Newtonsoft json deserialization - key as property

From Dev

Dynamic property name concatenation

From Dev

Newtonsoft JSON get specific nested property at runtime

From Dev

Serialize Dictionary without property name with Newtonsoft.Json

From Dev

Dynamic property name as string

From Dev

Newtonsoft.Json Custom Root Name for Deserialization

From Dev

ASP.NET MVC. Create model to convert into JSON-object (with dynamic name property)

From Dev

JSON Own Property Name

From Dev

Serialize Dynamic Property Name for an Object using JSON.NET

From Dev

How to update a property of a JSON object using NewtonSoft

From Dev

How to make an anonymous types property name dynamic?

From Dev

Sorting a JSON by value of a dynamic name property

From Dev

Parsing dynamic JSON with Newtonsoft.JSON is missing array in the deserialized object

From Dev

Reference a javascript property with a dynamic name

From Dev

C# Newtonsoft JSON map property to array sub item

From Dev

Get property by dynamic key name?

From Dev

How to deserialize to class with variable type property using NewtonSoft Json?

From Dev

Deserializing JSON with dynamic property

From Dev

Newtonsoft Json dynamic objects

From Dev

Parsing dynamic JSON array in C# using Newtonsoft

From Dev

dynamic dictionary name decoder json

From Dev

Newtonsoft Deserialize to Object Store Underlying JSON as property

From Dev

How do I convert json string without name with Newtonsoft?

Related Related

  1. 1

    Newtonsoft.Json DeserializeXmlNode changes tag name from number to "something"

  2. 2

    .NET NewtonSoft JSON deserialize map to a different property name

  3. 3

    Serialize Dynamic Property Name for an Object using JSON.NET

  4. 4

    How to update a property of a JSON object using NewtonSoft

  5. 5

    How to make an anonymous types property name dynamic?

  6. 6

    Deserialize Dynamic JSON file C# NewtonSoft.JSON

  7. 7

    Newtonsoft json deserialization - key as property

  8. 8

    Dynamic property name concatenation

  9. 9

    Newtonsoft JSON get specific nested property at runtime

  10. 10

    Serialize Dictionary without property name with Newtonsoft.Json

  11. 11

    Dynamic property name as string

  12. 12

    Newtonsoft.Json Custom Root Name for Deserialization

  13. 13

    ASP.NET MVC. Create model to convert into JSON-object (with dynamic name property)

  14. 14

    JSON Own Property Name

  15. 15

    Serialize Dynamic Property Name for an Object using JSON.NET

  16. 16

    How to update a property of a JSON object using NewtonSoft

  17. 17

    How to make an anonymous types property name dynamic?

  18. 18

    Sorting a JSON by value of a dynamic name property

  19. 19

    Parsing dynamic JSON with Newtonsoft.JSON is missing array in the deserialized object

  20. 20

    Reference a javascript property with a dynamic name

  21. 21

    C# Newtonsoft JSON map property to array sub item

  22. 22

    Get property by dynamic key name?

  23. 23

    How to deserialize to class with variable type property using NewtonSoft Json?

  24. 24

    Deserializing JSON with dynamic property

  25. 25

    Newtonsoft Json dynamic objects

  26. 26

    Parsing dynamic JSON array in C# using Newtonsoft

  27. 27

    dynamic dictionary name decoder json

  28. 28

    Newtonsoft Deserialize to Object Store Underlying JSON as property

  29. 29

    How do I convert json string without name with Newtonsoft?

HotTag

Archive