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


#1

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:
Thanks!


#2

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


#3

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.


#4

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())


#5

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!


#6

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.


#7

: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.