using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
public static void Main()
var users = new List<UserDTO>
new UserDTO { Id = 1, Name = "Joe Schmoe" },
new UserDTO { Id = 2, Name = "John Doe" },
new UserDTO { Id = 3, Name = "Bob Smith" }
PagedData<UserDTO> data1 = new PagedData<UserDTO>(users, 3, 1, 0, 10);
JsonSerializerSettings settings = new JsonSerializerSettings
ContractResolver = new CustomResolver(),
Formatting = Formatting.Indented
string json = JsonConvert.SerializeObject(data1, settings);
Console.WriteLine(new string('-', 40));
var items = new List<ItemDTO>
new ItemDTO { Id = 1, Name = "Hammer" },
new ItemDTO { Id = 2, Name = "Saw" },
new ItemDTO { Id = 3, Name = "Drill" },
new ItemDTO { Id = 4, Name = "Wrench" },
PagedData<ItemDTO> data2 = new PagedData<ItemDTO>(items, 4, 1, 0, 10);
json = JsonConvert.SerializeObject(data2, settings);
Console.WriteLine(new string('-', 40));
var berries = new List<Berry>
new Berry { Name = "Strawberry" },
new Berry { Name = "Blueberry" },
new Berry { Name = "Raspberry" },
new Berry { Name = "Blackberry" },
PagedData<Berry> data3 = new PagedData<Berry>(berries, 4, 1, 0, 10);
json = JsonConvert.SerializeObject(data3, settings);
public class JsonPropertyNameBasedOnItemClassAttribute : Attribute
public class JsonPluralNameAttribute : Attribute
public string PluralName { get; set; }
public JsonPluralNameAttribute(string pluralName)
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);
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";
public class PagedData<T>
public PagedData(IEnumerable<T> data, int count, int currentPage, int offset, int rowsPerPage, int? previousPage = null, int? nextPage = null)
CurrentPage = currentPage;
RowsPerPage = rowsPerPage;
PreviousPage = previousPage;
[JsonPropertyNameBasedOnItemClass]
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; }
[JsonPluralName("Users")]
public int Id { get; set; }
public string Name { get; set; }
[JsonPluralName("Items")]
public int Id { get; set; }
public string Name { get; set; }
public string Name { get; set; }