An issue with MutableDocument.SetData(props) and Json.Net-serialized object hierarchies

Hi there,

Trying to store an instance of a simple object hierarchy into a Couchbase.Lite database (v 2.0.0-db022). In order to deserialize the document into a concrete type the Json.Net serializer is configured to inject ‘$type’ meta-properties where needed. However, adding such a serialized Dictionary<string, object> to a MutableDocument over SetData() method results in a loss of the aforementioned type meta-properties, thus rendering deserialization attempts invalid.

Any particular reason why a property named ‘$type’ would be swallowed?

I have compiled a simple C# snippet to demonstrate the issue:

    public static void Main(string[] args)
        var doc = new Dictionary<string, object>
                "items", new JArray()
                    new JObject
                        { "$type", new JValue("value1") }

        var mDoc = new MutableDocument("1");
        mDoc.SetData(doc); //mDoc will not have it

In case you exchange the meta-property name to anything else (e.g., ‘$test’) the resulting mutable document will hold the property.

Any help appreciated :slight_smile:

That’s interesting. I didn’t think that there should be anything that prohibited the use of “$type” as the dictionary key. I didn’t try on .Net but I tested on iOS with a “$type” property name and it worked fine. Tagging @borrrden

I think the problem could be related to the use of Json.Net. When I set the data like this:

var dbDoc = new Couchbase.Lite.MutableDocument(“test-doc”);
dbDoc.SetData(new System.Collections.Generic.Dictionary<string, object>
{ { “items”, new object[] { new System.Collections.Generic.Dictionary<string, object> {
{ “$type”, “value1” } } } } });

Then the $type = value1 is contained in the MutableDocument. When I set the data using Json.Net like you did:

var dbDoc2 = new Couchbase.Lite.MutableDocument(“test-doc2”);
dbDoc2.SetData(new System.Collections.Generic.Dictionary<string, object>
{ { “items”, new Newtonsoft.Json.Linq.JArray() { new Newtonsoft.Json.Linq.JObject {
{ “$type”, new Newtonsoft.Json.Linq.JValue(“value1”) } } } } });

Then the $type value is missing.

The first thing I would think is that JValue is being rejected as an invalid class for serialization to Fleece. That would show up in logs if you enable text logging (Support.EnableTextLogging())

Hm, it looks to me that it has nothing to do with the JValue itself but rather the value of the key. Picking up on the example suggested by @avia_bdg - the moment you change “$type” to something else (lets say “$typee”) the key-value pair will be contained.

Could it be that the key value “$type” is used internally as some sort of a guide to the serializer behavior?

The enabled text logging yielded a silent file :frowning:

p.s. I’m not so much glued to the Json.Net - using it barely as a serialization/deserialization engine. Any library capable of performing a fast/reliable object hierarchy (de-)serialization into a structure fulfilling MutableDocument expectations would do the trick. In case you are aware of some please suggest.

Many thanks!

That’s not the case as noted in my previous response. Jim’s suggestion is more probable. Of course, there may still be a bug some where but by design, there is nothing preventing its usage.

:thinking: There’s nothing in CBL that reacts specially to $type or any $-prefixed key, so it must be some other layer doing this.

We do reject _-prefixed keys for compatibility reasons, and we treat an object with "@type":"blob" as a blob, but otherwise we pay no attention to what keys you use.