Click here to Skip to main content
Click here to Skip to main content

fastBinaryJSON

By , 20 Apr 2013
 

Preface 

The code is now on CodePlex under Git source control (http://fastbinaryjson.codeplex.com/).

Introduction 

fastBinaryJSON is based on my fastJSON article (http://www.codeproject.com/Articles/159450/fastJSON) and code which is a polymorphic object serializer. The main purpose for fastBinaryJSON is speed in serializing and deserializing data for the use in data transfer and storage to disk. It was created for my upcoming RaptorDB -  Document Database engine, for performance.

Features

fastBinaryJSON has the following feature list: 

  • Based on fastJSON code base (very fast, polymorphic)
    • Supports : HashTables, Dictionary, Generic Lists, Datasets, ...
  • Typically 2-10% faster on serialize, 17%+ faster on deserialize. 

Why?

Why another serializer you may ask, why not just use fastJSON? The answer to this is simple : performance. JSON while a great format has the following problem:

  • JSON is a text format, so you loose type information on serializing which makes deserializing the data again time consuming. 

Why not BSON?

Why not just use BSON (http://bsonspec.org/) you may ask? The answer is the following:

  • Looking at the specifications on the above site, you feel overwhelmed as it is hard to follow.
  • You feel that the specs have evolved over time and a lot of the coding parts have been deprecated.
  • BSON encodes lengths into the stream which inflate the data, this might be fine for the use case the authors envisioned, but for data transfer and storage it just makes things larger than they need to be.
  • Because of the length prefixes, the encoding of the data object must be done in two passes, once to output the data, and a second time to set the length prefixes.

I initially started off by doing a BSON conversion on fastJSON but it got too complicated, so it was scrapped.  

How is data encoded in fastBinaryJSON?  

JSON is an extremely simple format, so fastBinaryJSON takes that simplicity and add the needed parts to do binary serialization. fastBinaryJSON follows the same rules as the JSON specification (http://json.org) with the following table showing how data is encoded: 

As you can see  from the above all the encoding rules are the same as JSON and primitive data types have been given 1 byte tokens for encoding data. So the general format is :

TOKEN,  { DATA } : where DATA can be 0 or more bytes

Strings can be encoded in 2 ways, as UTF8 or Unicode, where UTF8 is more space efficient and Unicode is faster.

String keys or property names are encoded as a special UTF8 stream which is limited to 255 bytes in length to save space (you should not have a problem with this as most property names are short in length).

Performance tests

To get a sense of the performance differences in fastBinaryJSON against fastJSON the following tests were performed, times are in milliseconds, each test was done on 1000 objects and repeated 5 times, the AVG column is the average of the test excluding the first which is skewed by initialization times:


As you can see in the DIFF column which is [ fastJSON / fastBinaryJSON ] the serializer performs at least 2% faster  and the deserializer at least 17% faster, with the greatest difference being with DataSet types which are a lot of rows of data.

Using the code 

To use fastBinaryJSON you can use the following code samples:

byte[] bytes = fastBinaryJSON.BJSON.Instance.ToJSON(obj);
byte[] bytes = fastBinaryJSON.BJSON.Instance.ToJSON(obj, true, true); // optimized dataset, unicode strings

object obj = fastBinaryJSON.BJSON.Instance.ToObject(bytes);
SalesInvoice obj = fastBinaryJSON.BJSON.Instance.ToObject<SalesInvoice>(bytes); // type is known 

There are 3 parameters which control how the serialization is done which can be set on the Instance or can be done by a per call basis like the above examples :

UseOptimizedDatasetSchemaUse an optimized format to serialze the Dataset Schema (default = True)
ShowReadOnlyPropertiesSerialize ReadOnly Properties (default = False)
UseUnicodeStringsUse Unicode encoding for strings (default = True)

History    

  • Initial Release : 25th March 2012 
  • Update : 26th March 2012
    • Added link to codeplex source control
  • Update v1.1 : 26th May 2012
    • bug fix datetime to local time
    • added BJSONParameters
    • added global types (reverse format from fastJSON to overcome size limits on name strings)
  • Update v1.2 : 24th July 2012
    • refactored reflection code into Reflection class
    • added support for top level struct object serialize/deserialize 
  • Update v1.3 : 11th August 2012
    • bug fix reflection code
    • added unit tests
    • changed ArrayList to List<object>
    • updated code to be similar to fastJSON
    • deserialize ToObject< Dictionary<T,V> > 
    • deserialize ToObject< List<T> >
    • added FillObject method
  • Update v1.3.1 : 16th August 2012
    • bug fix $types and arrays
    • optimize writing $types 
  • Update v1.3.2 : 7th September 2012
    • null object serialize fixed
    • added sealed keyword to classes
    • bug fix SerializeNullValues=false and an extra comma at the end
    • FillObject nested types
  • Update v1.3.3 : 17th September 2012 
    • bug fix deserialize zero length arrays
    • test for German locale numbers
  • Update v1.3.4 :  20th September 2012
    • singleton uses ThreadStatic for concurrency (thanks to Philip Jander)
    • bug fix extra comma in the output when only 1 property in the object (thanks to Philip Jander)
  • Update v1.3.5 :  16th November 2012  
    • added support for root level DataSet and DataTable deserialize (you have to do ToObject<DataSet>(...) )
    • added dataset tests
    • added MonoDroid project
  • Update v1.3.7 : 20th April 2013
    • customtype is now builtin
    • added UseUTCTimes property for datetime
    • switched to properttype enum instead of booleans
    • using switch instead of linked if statements
    • unified DynamicMethod between silverlight and full .net
    • SafeDictionary lock fixes

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mehdi Gholam
Architect
United Kingdom United Kingdom
Member
Mehdi first started programming when he was 8 on BBC+128k machine in 6512 processor language, after various hardware and software changes he eventually came across .net and c# which he has been using since v1.0.
He is formally educated as a system analyst Industrial engineer, but his programming passion continues.
 
* Mehdi is the 5th person to get 6 out of 7 Platinums on CodeProject (13th Jan'12)

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerRe: ParseArray Bug?membercqwydz19 May '12 - 2:49 
if Array is Empty
object o = ParseValue(out breakparse);
o == 4,
byte t = GetToken();
t = 2 can't break while
AnswerRe: ParseArray Bug?mvpMehdi Gholam19 May '12 - 4:00 
Please supply the code for the object you are trying to serialize and you get this error.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: ParseArray Bug?membercqwydz20 May '12 - 6:56 
public class Test
{
public string Name { get; set; }
public Test2 Test2 { get; set; }
}
 
public class Test2
{
public string Name { get; set; }
public int Age { get; set; }
public List List { get; set; }
}
 
var tt = new Test();
tt.Name = "tt";
tt.Test2 = new Test2();
tt.Test2.Name = "tt2";
tt.Test2.List = new List();
 
var bc = fastBinaryJSON.BJSON.Instance.ToJSON(tt);
var cb = fastBinaryJSON.BJSON.Instance.ToObject(bc);
GeneralRe: ParseArray Bug?mvpMehdi Gholam20 May '12 - 7:34 
Thanks, I will check it out.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

Questionjavascript ?memberchristoph braendle30 Apr '12 - 1:20 
congrats to this great format Smile | :)
are any plans to have a JavaScript library to consume fastBinaryJSON directly?
AnswerRe: javascript ?mvpMehdi Gholam30 Apr '12 - 1:31 
As far as I know JSON (text version) is a first class citizen in javascript, so it would be easier to use that as javascript already understands and converts "types" as needed.
 
fastBinaryJSON is mostly intended for compiled languages with types which get lost in the conversion process.
 
So the answer would be no ( although it is mostly out of my league Wink | ;) as I am not a web developer).
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: javascript ?memberchristoph braendle30 Apr '12 - 2:21 
unfortunately JsonH https://github.com/WebReflection/JSONH[^] or something similar are not widely supported.
 
because I am not a web developer either, I will wait and see, seems to me the next logical step in JavaScript.
QuestionIDictionary<string, object>?memberHuisheng Chen17 Apr '12 - 15:14 
Hi, does it support IDictionary?
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

AnswerRe: IDictionary?mvpMehdi Gholam17 Apr '12 - 20:38 
fastBinaryJSON supports all of what fastJSON supports, so yes it does handle the IDictionary interface.
 
If you find any problems, please let me know.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: IDictionary?memberHuisheng Chen18 Apr '12 - 12:22 
IDictionary<string, object> dd = new Dictionary<string, object>();
            dd.Add("hello", new class1("asda", "asdas", Guid.NewGuid()));
            var rr = fastBinaryJSON.BJSON.Instance.ToJSON(dd);
            var res = fastBinaryJSON.BJSON.Instance.ToObject<Dictionary<string, object>>(rr); //will work
            var res = fastBinaryJSON.BJSON.Instance.ToObject<IDictionary<string, object>>(rr); //will not work
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

GeneralRe: IDictionary?mvpMehdi Gholam18 Apr '12 - 18:54 
Lost in translation...
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: IDictionary?memberHuisheng Chen18 Apr '12 - 19:29 
sorry, back to life now Laugh | :laugh: please have a look
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

GeneralRe: IDictionary?mvpMehdi Gholam18 Apr '12 - 19:36 
IDictionary is really an interface to something concrete.
 
So you can't really create an interface in the air, it must be bound to an actual class.
 
Hope that helps.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: IDictionary?memberHuisheng Chen18 Apr '12 - 20:08 
Hi, that does make sense. However, Json.net does support itConfused | :confused:
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

GeneralRe: IDictionary?mvpMehdi Gholam18 Apr '12 - 20:28 
Json.net is probably creating the underlying class for you.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: IDictionary?memberdave.dolan24 Jul '12 - 1:49 
Or perhaps just substituting System.Collections.Generic.Dictionary instead
GeneralRe: IDictionary?mvpMehdi Gholam24 Jul '12 - 2:04 
Smile | :)
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

QuestionCombine fastJson and fastBinaryJson?memberAnton Afanasyev10 Apr '12 - 14:29 
Have you considered combining the two projects into one with pluggable 'storage backend', so to speak?
Badger | [badger,badger,badger,badger...]

AnswerRe: Combine fastJson and fastBinaryJson?mvpMehdi Gholam10 Apr '12 - 18:18 
Thanks Anton,
 
Yes and no.
 
While bundling them both together would make a lot of sense and I am using them both, I doubt that most people would care for the binary part and a lot of fastJSON's appeal is the fact that it is so tiny in comparison to other implementations.
 
Currently fastBinaryJSON is non standard (my own invention, although I don't know why someone didn't do this before), so time will tell...
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: Combine fastJson and fastBinaryJson?memberAnton Afanasyev12 Apr '12 - 20:05 
Totally valid points. But I didn't quite mean to bundle them together. I haven't yet had a look at the fastBJ code, but I image that the general layout is the same as in fastJ, with only the actual writing (and reading) being different. So why not abstract the reading/writing into an interface, IReaderWriter, and inherit two classes from that interface: JsonReaderWriter, and BJsonReaderWriter. Then, you could do things such as:
var o = fastJson.Instance<JsonReaderWriter>.ToObject<MyObjectType>(responseFromSomeService);
var bData = fastJson.Instance<BJsonReaderWriter>.ToJSON( o );
// now do something with bData...e.g. save to disk
as an aside: JsonReaderWriter and BJsonReaderWriter could, theoretically, also be substituted for other, custom built types, althought THAT is something I seriously doubt.
 
This way, you can split the core of this thing into a separate assembly, and the different IReaderWriter's can be referenced by the developer using fastJson as needed.
 
I might get around to trying this out at some point myself, as it seems like an interesting idea to me, and I'd love to hear any input you may have.
Badger | [badger,badger,badger,badger...] "impossible" is just an opinion.

GeneralRe: Combine fastJson and fastBinaryJson?mvpMehdi Gholam12 Apr '12 - 20:23 
Good idea, this will require a lot of refactoring in the code.
 
One problem is that you would not be able to unify the external interfaces as of outputs strings and the other byte arrays.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

Questionunsafemembercqwydz28 Mar '12 - 19:22 
silverlight unsafe can't compile
AnswerRe: unsafemvpMehdi Gholam28 Mar '12 - 19:44 
Yes, thanks, the silverlight project is from fastJSON and I haven't tested it yet ( $types needs to be fixed )
 
I will post an update soon.
Its the man, not the machine - Chuck Yeager
If at first you don't succeed... get a better publicist
If the final destination is death, then we should enjoy every second of the journey.

GeneralRe: unsafemembercqwydz28 Mar '12 - 23:06 
use BitConverter work good.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 20 Apr 2013
Article Copyright 2012 by Mehdi Gholam
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid