问题
I want to modify JSON.NET so that when I am serializing a Model from my API it sends only an array of IDs for a composite Collection object.
For example:
class Employee
{
public ICollection<Address> Addresses { get; set; }
}
class Address
{
public int id;
public string location;
public string postcode;
}
Then when I send that back through WebApi
Request.Createresponse(HttpStatusCode.OK, new Employee());
Instead of this:
{
"Addresses" :
[
{"id" : 1, "location" : "XX", "postcode" : "XX" },
{"id" : 2, "location" : "XX", "postcode" : "XX" }
]
}
It just sends as this:
{
"Addresss" : [1,2]
}
I want this to be happening application-wide and I don't want to modify at the specific place.
How can I achieve this using the JSON.NET serializer?
回答1:
You can get the result you want using a custom JsonConverter such as this:
class IdOnlyListConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (typeof(IEnumerable).IsAssignableFrom(objectType) &&
objectType != typeof(string));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
JArray array = new JArray();
foreach (object item in (IEnumerable)value)
{
PropertyInfo idProp = item.GetType().GetProperty("id");
if (idProp != null && idProp.CanRead)
{
array.Add(JToken.FromObject(idProp.GetValue(item, null)));
}
}
array.WriteTo(writer);
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
In your model, wherever you have a collection of something where you only want the IDs, decorate the collection property with a [JsonConverter]
attribute specifying the custom converter. For example:
class Employee
{
public string name { get; set; }
[JsonConverter(typeof(IdOnlyListConverter))]
public ICollection<Address> Addresses { get; set; }
}
class Address
{
public int id { get; set; }
public string location { get; set; }
public string postcode { get; set; }
}
When the collection gets serialized, the converter will be used, and only the ID values will be written out. Demo:
class Program
{
static void Main(string[] args)
{
Employee emp = new Employee
{
name = "Joe",
Addresses = new List<Address>
{
new Address { id = 1, location = "foo", postcode = "bar" },
new Address { id = 2, location = "baz", postcode = "quux" }
}
};
string json = JsonConvert.SerializeObject(emp);
Console.WriteLine(json);
}
}
Output:
{"name":"Joe","Addresses":[1,2]}
回答2:
Please have a look at Json.Net's documentation.
public class Address
{
[JsonProperty("Id")]
public int I'd { get; set; }
[JsonIgnore]
public string Location { get; set; }
[JsonIgnore]
public string PostalCode { get; set; }
}
The only drawback to this is that you'll never be able to serialize the Location and PostalCode properties to JSON should you ever want to.
I believe there is a way to specify the serialization that should be used when serializing to JSON with Json.Net. Again, have a look at their documentation.
来源:https://stackoverflow.com/questions/24976779/modify-the-behaviour-of-json-net-to-serialize-a-collection-of-objects-to-an-arra