Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to handle versioning using JSON protocol?

I am normally writing all parts of the code in C# and when writing protocols that are serialized I use FastSerializer that serializes/deserializes the classes fast and efficient. It is also very easy to use, and fairly straight-forward to do "versioning", ie to handle different versions of the serialization. The thing I normally use, looks like this:

public override void DeserializeOwnedData(SerializationReader reader, object context) {     base.DeserializeOwnedData(reader, context);     byte serializeVersion = reader.ReadByte(); // used to keep what version we are using      this.CustomerNumber = reader.ReadString();     this.HomeAddress = reader.ReadString();     this.ZipCode = reader.ReadString();     this.HomeCity = reader.ReadString();     if (serializeVersion > 0)         this.HomeAddressObj = reader.ReadUInt32();     if (serializeVersion > 1)         this.County = reader.ReadString();     if (serializeVersion > 2)         this.Muni = reader.ReadString();     if (serializeVersion > 3)         this._AvailableCustomers = reader.ReadList<uint>(); } 

and

public override void SerializeOwnedData(SerializationWriter writer, object context) {                 base.SerializeOwnedData(writer, context);     byte serializeVersion = 4;      writer.Write(serializeVersion);       writer.Write(CustomerNumber);     writer.Write(PopulationRegistryNumber);                 writer.Write(HomeAddress);     writer.Write(ZipCode);     writer.Write(HomeCity);     if (CustomerCards == null)         CustomerCards = new List<uint>();                 writer.Write(CustomerCards);     writer.Write(HomeAddressObj);      writer.Write(County);      // v 2     writer.Write(Muni);      // v 4     if (_AvailableCustomers == null)         _AvailableCustomers = new List<uint>();     writer.Write(_AvailableCustomers); } 

So its easy to add new things, or change the serialization completely if one chooses to.

However, I now want to use JSON for reasons not relevant right here =) I am currently using DataContractJsonSerializer and I am now looking for a way to have the same flexibility I have using the FastSerializer above.

So the question is; what is the best way to create a JSON protocol/serialization and to be able to detail the serialization as above, so that I do not break the serialization just because another machine hasn't yet updated their version?

like image 358
Ted Avatar asked Apr 06 '12 11:04

Ted


People also ask

What is JSON how is it useful for sending and storing data?

It is a text-based way of representing JavaScript object literals, arrays, and scalar data. JSON is relatively easy to read and write, while also easy for software to parse and generate. It is often used for serializing structured data and exchanging it over a network, typically between a server and web applications.

What are the reasons to choose JSON as one the preferred data format to transfer the data while working with JSON?

JSON is a wildly successful way of formatting data for several reasons. First, it's native to JavaScript, and it's used inside of JavaScript programs as JSON literals. You can also use JSON with other programming languages, so it's useful for data exchange between heterogeneous systems. Finally, it is human readable.

Is JSON good for storing data?

JSON is a great format to store data, widely used in JavaScript but not only - discover all about it! JSON is a file format that's used to store and interchange data. Data is stored in a set of key-value pairs. This data is human readable, which makes JSON perfect for manual editing.

Which data types are directly supported by JSON?

JSON supports a value of type String, Number and Boolean. It does not support octal and hexdecimal values.


1 Answers

The key to versioning JSON is to always add new properties, and never remove or rename existing properties. This is similar to how protocol buffers handle versioning.

For example, if you started with the following JSON:

{   "version": "1.0",   "foo": true } 

And you want to rename the "foo" property to "bar", don't just rename it. Instead, add a new property:

{   "version": "1.1",   "foo": true,   "bar": true } 

Since you are never removing properties, clients based on older versions will continue to work. The downside of this method is that the JSON can get bloated over time, and you have to continue maintaining old properties.

It is also important to clearly define your "edge" cases to your clients. Suppose you have an array property called "fooList". The "fooList" property could take on the following possible values: does not exist/undefined (the property is not physically present in the JSON object, or it exists and is set to "undefined"), null, empty list or a list with one or more values. It is important that clients understand how to behave, especially in the undefined/null/empty cases.

I would also recommend reading up on how semantic versioning works. If you introduce a semantic versioning scheme to your version numbers, then backwards compatible changes can be made on a minor version boundary, while breaking changes can be made on a major version boundary (both clients and servers would have to agree on the same major version). While this isn't a property of the JSON itself, this is useful for communicating the types of changes a client should expect when the version changes.

like image 135
monsur Avatar answered Sep 24 '22 02:09

monsur