我有以下型号:
public interface IEntity
{
string Id { get; }
}
public class EntityParent : IEntity
{
public string Id { get; }
public EntityChild EntityChild { get; }
[JsonConstructor]
public EntityParent(string id, EntityChild entityChild)
{
Id = id;
EntityChild = entityChild;
}
}
public class EntityChild : IEntity
{
public string Id { get; }
public int Age { get; }
[JsonConstructor]
public EntityChild(string id, int age)
{
Id = id;
Age = age;
}
}
接下来,我需要将一些JSON反序列化为上述类型的集合:
{
"Children":
[
{
"Id" : "Billy",
"Age" : 42
}
],
"Parents" :
[
{
"Id" : "William",
"EntityChild" : "Billy"
}
]
}
最终我希望有一个EntityChild
ren列表和一个EntityParent
列表,它们(可选)包含对第一个列表中对象的引用,或者至少引用{{1}个实例的引用1}}。我试图编写一个自定义EntityChild
(我正在使用 Newtonsoft.Json 9.0.1 NuGet包),在JsonConverter
方法中我正在寻找一个具有特定性的孩子ReadJson()
,如此:
Id
这是一个简单的测试:
public class ParentConverter<TEntity> : JsonConverter where TEntity : IEntity
{
private readonly IEnumerable<TEntity> _children;
public ParentConverter(IEnumerable<TEntity> children)
{
_children = children;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
JObject jObject = JObject.Load(reader);
TEntity target = _children.FirstOrDefault(d => d.Id == jObject["Id"].ToString());
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override bool CanConvert(Type objectType)
{
return typeof(TEntity).IsAssignableFrom(objectType);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public class JsonTest
{
const string Json = @"
{
""Children"": [
{
""Id"" : ""Billy"",
""Age"" : 42
}
],
""Parents"" : [
{
""Id"" : ""William"",
""EntityChild"" : ""Billy""
}
]
}";
public static void Main()
{
JObject jObject = JObject.Parse(Json);
var children =
JsonConvert.DeserializeObject<List<EntityChild>>(jObject["Children"].ToString());
var parents =
JsonConvert.DeserializeObject<List<EntityParent>>(jObject["Parents"].ToString(),
new ParentConverter<EntityChild>(children));
}
}
已正确反序列化,但children
尝试在parents
中调用JsonReaderException
时抛出JObject.Load(reader);
,说&#34; 错误从JsonReader读取JObject。当前的JsonReader项不是对象:String。路径&#39; [0] .EntityChild&#39;。&#34;
有谁知道我应该怎么做?提前谢谢。
修改:使用额外属性更新了ReadJson()
,以强调EntityChild
上的媒体资源必须为EntityParent
类型,不是串
答案 0 :(得分:2)
实体父母应如下所示:
public class EntityParent : IEntity
{
public string Id { get; }
public string EntityChild { get; }
[JsonConstructor]
public EntityParent(string id, string entityChild)
{
Id = id;
EntityChild = entityChild;
}
}
并在main()
更改如下:
var parents = JsonConvert.DeserializeObject<List<EntityParent>>(jObject["Parents"].ToString());
它有效。
答案 1 :(得分:0)
以下是一种使用LINQ的解决方法,我基本上将子JObject与子JOASEs连接起来构建父级和子级:
public static void Main()
{
JObject jObject = JObject.Parse(Json);
IEnumerable<EntityParent> parents =
from parent in jObject["Parents"]
join child in jObject["Children"] on parent["EntityChild"] equals child["Id"]
select
new EntityParent(
parent["Id"].ToString(),
new EntityChild(
child["Id"].ToString(),
child["Age"].ToObject<int>()));
}
如果已存在子列表,则可以在该列表上执行连接,如下所示:
public static void Main()
{
JObject jObject = JObject.Parse(Json);
var children =
JsonConvert.DeserializeObject<List<EntityChild>>(jObject["Children"].ToString());
IEnumerable<EntityParent> parents =
from parent in jObject["Parents"]
join child in children on parent["EntityChild"] equals child.Id
select new EntityParent(parent["Id"].ToString(), child);
}