我使用.NET / MyCouch将普通POCO对象读/写到NoSQL存储(couchdb)。这很好用,对于关系简单的对象也可以正常工作。
我想表达关系" ids"我正在研究的项目NoSQL / MyCouch中的类型之间,我想更多地了解如何充分利用JSon.NET(MyCouch使用Json.net)。 / p>
例如:登录有很多用户
class Common {
public string _id;
public string _rev;
... more here, including ID generation ...
}
class Login : Common {
public string Name {get;set;}
public List<User> users {get;set;}
}
class User : Common {
public string email {get;set};
}
保存用户会产生嵌套的JSON文档:
{
"name": "Neil"
...
"users": [
{
"_id": "user:foo:something",
"_rev": "32-92cca77ee07b8149b8d3dd76f8c8b08d"
"email": "foo@there.com"
...
},
...
]
}
在正常情况下,MyCouch(通过Json.NET序列化)遍历关系并生成嵌套的JSON。耶。
&#39;普通&#39;是一个包含ID的基类,并且还将ID存储为对象类型的混合:代码:UUID(因此&#39;用户:foo:某些&#39;以上示例)。
我宁愿做的是为用户生成对象ID,但仅针对这些类型的关系。不是每个从Common继承的对象(所有这些都是)。我非常确定我可以为所有Common对象添加一个转换器,但是这样就可以打破所有对象的基本序列化。我只想创建&#34; ID列表&#34;实际的列表关系。
我想像这样的JSON doc输出:
{
name: "Neil"
...
users: ["user:foo:something", ... ]
}
我可以通过自定义Json.NET序列化程序来完成此任务:
[JsonConverterAttribute(typeof(ReferenceListConverter), typeof(User))]
public List<User> Users { get; set; }
这适用于输出。我得到了我想要的东西。 这是ReferenceListConverter:
public class ReferenceListConverter : JsonConverter
{
private Type expectedType;
public override bool CanRead => true;
public override bool CanWrite => true;
public ReferenceListConverter(Type expectedType)
{
this.expectedType = expectedType;
}
public override bool CanConvert(Type objectType)
{
return typeof(Common).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// Get the _id, and _rev, and construct a real object from those
// In this case, it means making another request to the server.
var listType = typeof(List<>);
var list = listType.MakeGenericType(this.expectedType);
if (reader.TokenType != JsonToken.Null)
{
if (reader.TokenType == JsonToken.StartArray)
{
JToken token = JToken.Load(reader);
List<string> items = token.ToObject<List<string>>();
// Construct some items
// ID's are of form <typename>:<id>
MethodInfo program = typeof(Program).GetMethod("FetchObjectsFromStore", System.Reflection.BindingFlags.Static | BindingFlags.Public);
MethodInfo generic = program.MakeGenericMethod(this.expectedType);
string[] parameters = items.ToArray();
var result = generic.Invoke(null, new object[] { parameters });
return result;
}
}
return list;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Write out only the ID of the object
JArray array = new JArray();
if(value is IEnumerable<Common>)
{
foreach (Common item in (IEnumerable<Common>)value)
{
array.Add(JToken.FromObject(item._id));
}
}
array.WriteTo(writer);
}
}
1)阅读......是有问题的。基本。但它适用于一个简单的案例。
我无法注射我的&#34; db&#34;通过IoC进行分类(我使用SimpleInjector并且已经知道如何使用IoC为单个字段注入特定的JsonConverter)。因此,ReferenceListConverter使用静态方法进行后续查找,这是&#34; meh&#34;,但在我学习的时候还可以。
2)这并没有考虑到周期。用户&lt; - &gt;登录,我有一个无限循环。
我的问题是知识渊博的Json.NET人:是否只是&#34;更好的方式&#34;去做这个?自定义Json.NET引用机制?其他?