我有以下JSON:
{
"id" : "2"
"categoryId" : "35"
"type" : "item"
"name" : "hamburger"
}
{
"id" : "35"
"type" : "category"
"name" : "drinks"
}
我希望将它与此对象匹配:
public class Item
{
[JsonProperty(PropertyName = "categoryId")]
public Category Category { get; set; }
}
Category
属于Entity
类型,其中包含string
Id
属性。我希望JSON反序列化器创建的“35”对象映射到Category
中的Item
属性。
根据to the documentation,我应该使用IReferenceResolver
。我如何实现此接口并将其挂钩到JSON.NET框架中?
答案 0 :(得分:11)
您可以在JsonSerializerSettings中指定自定义IRefenceResover:
JsonSerializerSettings settings = new JsonSerializerSettings ();
settings.ReferenceResolver = new IDReferenceResolver ();
对于具有 Guid id 属性的对象,有一个很好的IDReferenceResolver实现示例。引用字符串现在是对象的 id ,除了您使用 int 而不是 Guid 之外,它类似于您的用例你的id属性的类型。
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Serialization;
namespace Newtonsoft.Json.Tests.TestObjects
{
public class IdReferenceResolver : IReferenceResolver
{
private readonly IDictionary<Guid, PersonReference> _people = new Dictionary<Guid, PersonReference>();
public object ResolveReference(object context, string reference)
{
Guid id = new Guid(reference);
PersonReference p;
_people.TryGetValue(id, out p);
return p;
}
public string GetReference(object context, object value)
{
PersonReference p = (PersonReference)value;
_people[p.Id] = p;
return p.Id.ToString();
}
public bool IsReferenced(object context, object value)
{
PersonReference p = (PersonReference)value;
return _people.ContainsKey(p.Id);
}
public void AddReference(object context, string reference, object value)
{
Guid id = new Guid(reference);
_people[id] = (PersonReference)value;
}
}
}
答案 1 :(得分:1)
使用CustomCreationConverter<T>
作为JsonConverter并覆盖Create
和ReadJson
方法。
class ItemConverter : CustomCreationConverter<Item> {
public override Item Create(Type objectType)
{
return new Item();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
int categoryId = jObject["categoryId"].ToObject<int>();
Category category = Program.Repository.GetCategoryById(categoryId);
Item result = (Item)base.ReadJson(jObject.CreateReader(), objectType, existingValue, serializer);
result.Category = category;
return result;
}
}
class Item {
[JsonProperty("itemName")]
public string ItemName { get; set; }
public Category Category { get; set; }
// other properties.
}
class Category {
public int CategoryId { get; set; }
public string Name { get; set; }
// other properties.
}
class MockCategoryRepository {
IList<Category> _repository;
public MockCategoryRepository()
{
_repository = new List<Category>();
_repository.Add(new Category() { CategoryId = 1, Name = "Drink" });
_repository.Add(new Category() { CategoryId = 35, Name = "Food" });
_repository.Add(new Category() { CategoryId = 70, Name = "Fruit" });
}
public Category GetCategoryById(int id)
{
return _repository.Where(x => x.CategoryId == id).SingleOrDefault();
}
}
class Program {
public static MockCategoryRepository Repository { get; private set; }
static void Main(string[] args)
{
Repository = new MockCategoryRepository(); // initialize mock repository
// sample : json contains two items in an array.
string jsonString = @"
[
{ ""categoryId"":""35"", ""itemName"":""Item A"" },
{ ""categoryId"":""70"", ""itemName"":""Item B"" },
]";
List<Item> items = JsonConvert.DeserializeObject<List<Item>>(jsonString, new ItemConverter());
}
}
从同一个json字符串中获取Category
对象信息的条件的解决方案。
class ItemConverter : CustomCreationConverter<Item> {
readonly IEnumerable<Category> _repository;
public ItemConverter(IEnumerable<Category> categories)
{
_repository = categories;
}
public override Item Create(Type objectType)
{
return new Item();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
int categoryId = jObject["categoryId"].ToObject<int>();
Category category = _repository.Where(x => x.CategoryId == categoryId).SingleOrDefault();
Item result = (Item)base.ReadJson(jObject.CreateReader(), objectType, existingValue, serializer);
result.Category = category;
return result;
}
}
class Item {
[JsonProperty("name")]
public string Name { get; set; }
public Category Category { get; set; }
// other properties.
}
class Category {
[JsonProperty("id")]
public int CategoryId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
// other properties.
}
class Program {
static void Main(string[] args)
{
// sample : json contains items and/or categories in an array.
string jsonString = @"
[
{
""id"" : ""2"",
""categoryId"" : ""35"",
""type"" : ""item"",
""name"" : ""hamburger""
},
{
""id"" : ""35"",
""type"" : ""category"",
""name"" : ""drinks""
}
]";
JArray jsonArray = JArray.Parse(jsonString);
// Separate between category and item data.
IEnumerable<JToken> jsonCategories = jsonArray.Where(x => x["type"].ToObject<string>() == "category");
IEnumerable<JToken> jsonItems = jsonArray.Where(x => x["type"].ToObject<string>() == "item");
// Create list of category from jsonCategories.
IEnumerable<Category> categories = jsonCategories.Select(x => x.ToObject<Category>());
// Settings for jsonItems deserialization.
JsonSerializerSettings itemDeserializerSettings = new JsonSerializerSettings();
itemDeserializerSettings.Converters.Add(new ItemConverter(categories));
JsonSerializer itemDeserializer = JsonSerializer.Create(itemDeserializerSettings);
// Create list of item from jsonItems.
IEnumerable<Item> items = jsonItems.Select(x => x.ToObject<Item>(itemDeserializer));
}
}