Reputation: 6050
I have a nested object
public class CardListViewModel
{
public virtual Guid Id { get; set; }
public virtual IEnumerable<Card> CardList { get; set; }
}
public class Card
{
public virtual Guid Id { get; set; }
public virtual string IndexName { get; set; }
public virtual Image CardImage { get; set; }
}
public class Image
{
//...
public virtual string Src { get; set; }
//...
}
So card may be
CardListViewModel.CardList[0] = {Id:5678, IndexName:"Visa", {Src:"Visa.png"}}
CardListViewModel.CardList[1] = {Id:5555, IndexName:"MasterCard", {Src:"MasterCard.png"}}
The result I want is a Json object like the following
{
"Visa": "Visa.png",
"MasterCard": "MasterCard.png"
}
I can't modify the POCO, all I want is a JSON fragment for each card in the list and their corresponding image. Of course I can brute force this with StringBuilder
and loops, but I was wondering if there was a way to accomplish this with the JsonConvert
library or any other good tools that handle the mapping for me?
Upvotes: 1
Views: 52
Reputation: 116785
Given that I can't modify the POCO and you are looking to use json.net, you can create a custom JsonConverter
for objects of type IEnumerable<Card>
as follows:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public class CardListConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(IEnumerable<Card>).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var list = existingValue as ICollection<Card> ?? new List<Card>();
var obj = JObject.Load(reader);
foreach (var property in obj.Properties())
{
list.Add(new Card { IndexName = property.Name, CardImage = new Image { Src = (string)property.Value } });
}
return list;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var collection = (IEnumerable<Card>)value;
writer.WriteStartObject();
foreach (var item in collection)
{
writer.WritePropertyName(item.IndexName);
writer.WriteValue(item.CardImage == null ? null : item.CardImage.Src);
}
writer.WriteEndObject();
}
}
Then use it in serialization settings as follows:
var settings = new JsonSerializerSettings
{
Converters = { new CardListConverter() },
};
var json = JsonConvert.SerializeObject(CardListViewModel, Formatting.Indented, settings);
And your CardListViewModel
will be serialized as follows:
{
"Id": "c2a7cc0f-0e6b-40a0-9020-aeba436265d4",
"CardList": {
"Visa": "Visa.png",
"MasterCard": "MasterCard.png"
}
}
Sample fiddle.
Upvotes: 0
Reputation: 322
I'd use LINQ to map it and NewtonsoftJson to build the JSON.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Linq;
var mappedCards = JsonConvert.SerializeObject(new JObject (
from card in CardListViewModel.CardList
select new JProperty(card.IndexName, card.CardImage.Src)));
Upvotes: 2