title: Json.Net: Turn relations into references and back again (one->many)
body: <p>I'm using .NET/<a href="https://github.com/danielwertheim/mycouch" rel="nofollow noreferrer">MyCouch</a> to read/write plain POCO objects to a NoSQL store (couchdb). This works fine, and also works fine for objects with simple relations. </p>
  
  <p>I would like to express relations as "ids" between types in NoSQL/MyCouch for a project I'm working on, and I'm wanting to learn more about how I would make the most use of JSon.NET for this (MyCouch uses Json.net).</p>
  
  <p>e.g: Login has many Users</p>
  
  <pre><code>class Common {
     public string _id; 
     public string _rev;
     ... more here, including ID generation ...
  } 
  
  class Login : Common {
     public string Name {get;set;}
     public List&lt;User&gt; users {get;set;}
  }
  
  class User : Common {
     public string email {get;set};
  }
  </code></pre>
  
  <p>When saving a <strong>User</strong> yields a nested JSON doc:</p>
  
  <pre><code>{
     "name": "Neil"
     ...
     "users": [
        {
           "_id": "user:foo:something",
           "_rev": "32-92cca77ee07b8149b8d3dd76f8c8b08d"
           "email": "foo@there.com"
           ...
        },
        ...
     ]
  }
  </code></pre>
  
  <p>In the normal case, MyCouch (via Json.NET serialization) traverses the relationship and generates nested JSON. Yay.</p>
  
  <p>'Common' is a base class containing the ID, and also stores the ID as a mix of object type:code:UUID (hence the 'user:foo:something' example above).</p>
  
  <p>What I would rather do is generate object IDs to the users, <em>but only for these kinds of relationships</em>. Not for every object that inherits from Common (all of them do). I'm pretty sure I could add a converter for all Common objects, but figure that'd break the basic serialization of all objects. I only want to create "lists of IDs" for actual List relationships.</p>
  
  <p>I imagine JSON doc output like this:</p>
  
  <pre><code>{
     name: "Neil"
     ...
     users: ["user:foo:something", ... ]
  }
  </code></pre>
  
  <p>I can do this by customizing the Json.NET serializer:</p>
  
  <pre><code>    [JsonConverterAttribute(typeof(ReferenceListConverter), typeof(User))]
      public List&lt;User&gt; Users { get; set; }
  </code></pre>
  
  <p>This works great for output. I get exactly what I want.
  Here's ReferenceListConverter:</p>
  
  <pre><code>public class ReferenceListConverter : JsonConverter
  {
      private Type expectedType;
  
      public override bool CanRead =&gt; true;
  
      public override bool CanWrite =&gt; 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&lt;&gt;);
          var list = listType.MakeGenericType(this.expectedType);
          if (reader.TokenType != JsonToken.Null)
          {
              if (reader.TokenType == JsonToken.StartArray)
              {
                  JToken token = JToken.Load(reader);
                  List&lt;string&gt; items = token.ToObject&lt;List&lt;string&gt;&gt;();
  
                  // Construct some items
                  // ID's are of form &lt;typename&gt;:&lt;id&gt;
                  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&lt;Common&gt;)
          {
              foreach (Common item in (IEnumerable&lt;Common&gt;)value)
              {
                  array.Add(JToken.FromObject(item._id));
              }
          }
          array.WriteTo(writer);
      }
  }
  </code></pre>
  
  <p>1) Reading... is problematic. Basic. But it works for a simple case.</p>
  
  <p>I am unable to inject my "db" class via IoC (I'm using SimpleInjector and havn't figured out how I can inject a specific JsonConverter, for a single field, using IoC).  So ReferenceListConverter uses a static method to do it's subsequent lookups, which is "meh", but OK while I learn.</p>
  
  <p>2) This doesn't take into account cycles. As soon as User &lt;-> Logins, I have an infinite loop.</p>
  
  <p>My question is to knowledgeable Json.NET people: Is there just "a better way" to do this?  Customization of the Json.NET reference mechanisms? Other? </p>