c# - Json.Net:将关系转换为引用并再次返回(one->many)
问题描述
我正在使用 .NET/ MyCouch将普通 POCO 对象读/写到 NoSQL 存储 (couchdb)。这很好用,也适用于具有简单关系的对象。
对于我正在从事的项目,我想将 NoSQL/MyCouch 中类型之间的关系表示为“ids”,并且我想了解更多关于如何充分利用 JSon.NET 的信息(MyCouch 使用json.net)。
例如:登录有很多用户
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。耶。
'Common' 是一个包含 ID 的基类,并将 ID 存储为对象类型的混合:代码:UUID(因此上面的 'user:foo:something' 示例)。
我宁愿为用户生成对象 ID,但仅限于这些类型的关系。并非对于从 Common 继承的每个对象(所有对象都这样做)。我很确定我可以为所有 Common 对象添加一个转换器,但认为这会破坏所有对象的基本序列化。我只想为实际的列表关系创建“ID 列表”。
我想像这样的 JSON 文档输出:
{
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) 阅读……是有问题的。基本的。但它适用于一个简单的案例。
我无法通过 IoC 注入我的“db”类(我正在使用 SimpleInjector,但我不知道如何使用 IoC 为单个字段注入特定的 JsonConverter)。所以 ReferenceListConverter 使用静态方法来进行后续查找,即“meh”,但在我学习时还可以。
2)这不考虑周期。只要用户 <-> 登录,我就有一个无限循环。
我的问题是知识渊博的 Json.NET 人:有没有“更好的方法”来做到这一点?自定义 Json.NET 引用机制?其他?
解决方案
推荐阅读
- reactjs - 在雷达标签中添加不同颜色的数值
- sql - 如何在全文搜索中使用运算符(AND、OR、NOT 和 THE)作为关键字进行搜索
- webpack - Webpack 仅捆绑第一个更改
- docker - 如何在 Dockerfile 中的相对路径上指定我的图像以从头开始添加?
- firebase - 我无法在终端中运行 firebase 命令
- ruby-on-rails - EC2 实例用户数据脚本未完成运行
- sql-server - Visual Studio调试存储过程,逐行关注T-SQL CASE WHEN
- android - Android Compose - 具有 3 种类型的图像:颜色纯色、线性渐变、url
- python - django.db.utils.OperationalError:无法连接到服务器:连接
- ubuntu - 如何创建 shell 脚本来检查 Ubuntu 中 systemd 服务的状态?