Json.Net:将关系转换为引用并再次返回(一个>多个)

时间:2018-05-16 08:23:09

标签: c# json.net

我使用.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引用机制?其他?

0 个答案:

没有答案