views:

597

answers:

6

I'm thinking about throwing away my DB in my next project to simplify development/evolution.

One way to do it is not to leave the Objects realm at all and persist my objects by some kind of serialization. It would be nice to be able to edit the initial objecs state when the app is down, so format like Json would be great.

The problem is that JSON tools (like Java Jackson), or rather JSON itself, are not able to keep the references, so after deserializing object graph I can get more instances then I got before serialization - each reference to the same object gets new instance.

I've noticed JSPON but it doesn't seem to be alive.

What do you think about such approach - isn't it too simple to be possible? Or maybe I should use some OODB (although it would create additional configurational overhead and I want to keep it simple).

+4  A: 

Most of the simple portable serializers (xml, json, protocol buffers) are tree serializers (not graph serializers), so you'll see this problem a bit...

You could perhaps try using a DTO tree that doesn't need the references? i.e. instead of:

Parent -(children)-> Child
       <--(parent)--

you have (at the DTO level):

Parent {Key="abc"} -(child keys)-> {string}
Child {Key="def"} -(parent key)-> {string}

This should be usable with any tree serializer; but it does require extra (manual) processing.

There are graph-based serializers like .NET's DataContractSerializer (with graph-mode enabled; it is disabled by default); but this is non-portable.

Marc Gravell
Thanks for the appropriate distinction, it cleared my thoughts. I've found out that Xstream (xstream.codehaus.org/graphs.html) can deal with the graph serialization (I'm not sure yet whether it can also in JSON mode but I can live with XML).
deadbeef
+2  A: 

The references issue should be simple enough to solve assuming you control the serialization - you'd simply save the objects giving each an id and then save the references in terms of those ids.

However, while I think you'd get a simple version working and I reckon you'd run into problems down the line. Things that spring to mind are:

  • What would happen as the code evolves and the classes change?
  • How would you support query operations, particularly indexing to make the queries fast?
  • How would you manage concurrent access?
  • How would you manage transactions?
  • How would it scale?

I don't think these problems are insurmountable but IMHO, relational databases are the way they are based on years of development and use in the wild and the OODBs that I've seen are not a realistic proposition at this time.

Also, there's a whole class of problem that the set based logic provided by relational databases is ideal for, let alone the power of SQL in refining the data-sets you load, which just isn't as easy in the object world. With the modern ORMs making life so easy these days I certainly would want to confine myself to either realm.

Nick Holt
I agree with the issues you mention, although particular project I'm thinking about won't cope with most of them since it won't have to scale so concurrency can be solved by locking. Also there won't be lot of data, so performance/indexing also won't be an issue.Transactions - fair point, but also there's no need Schema evolution - true, connected with query problem (esp. no easy way to do mass update easily). LINQ and followers will make it easier, though.
deadbeef
@deadbeef - sure it'll be an interesting exercise either way, so try to post back to let us all know how it goes.
Nick Holt
+1  A: 

I've found this SO question helpful. XStream seems to cope with references by using relative paths in tree structure to the first reference when finding next one, even for json ( see here ).

Simple apparently can deal with more complex object graphs, but XStream seems more popular, does JSON and will probably suit my needs (I won't be having cyclic references even).

deadbeef
Note however that XStream really is an XML-based object serializer; so while it does have JSON compatibility support, it goes through JSON->XML converter (Jettison) so any size or performance benefits JSON may have are lost. So I would suggest just using XML, if going with XStream (which is a good tool for object serialization, that's what it's designed for).
StaxMan
A: 

As long as you're not leaving .NET realm, why not use the serialization mechanisms that .NET offers? It can easily serialize your object graphs (private fields included) to a binary blob and back again. There is also a built-in mechanism for serializing to and from XML, although that has some limitations when it comes to private fields and stuff (you can work around that though). There are also attributes that specify that some fields are newer and may not be in the serialized stream. You'll have to deal with them being NULL yourself, but then - you'd have to do that anyway.

Added: Ah, yes, forgot to mention - I'm talking about System.Runtime.Serialization.Formatters.Binary.BinaryFormatter class.

Vilx-
A: 

The latest version of Json.NET supports serializing references.

string json = JsonConvert.SerializeObject(people, Formatting.Indented,
  new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
//[
//  {
//    "$id": "1",
//    "Name": "James",
//    "BirthDate": "\/Date(346377600000)\/",
//    "LastModified": "\/Date(1235134761000)\/"
//  },
//  {
//    "$ref": "1"
//  }
//]

List<Person> deserializedPeople = JsonConvert.DeserializeObject<List<Person>>(json,
  new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });

Console.WriteLine(deserializedPeople.Count);
// 2

Person p1 = deserializedPeople[0];
Person p2 = deserializedPeople[1];

Console.WriteLine(p1.Name);
// James

Console.WriteLine(p2.Name);
// James

bool equal = Object.ReferenceEquals(p1, p2);
// true
James Newton-King
A: 

the itemscript project proposes a schema language based on JSON. itemscript schema describes data types. itemscript JAM is an application markup developed in itemscript.

the reference implementation includes a GWT client (Item Lens) and a column store (Item Store) that persists JSON data.