While working on a package manager for CMake I came across the problem of finding a suitable format for my package descriptor files. First I thought about and tried using plain old CMake file that simply sets variables and can be included to access its contents.  It was very quick and easy to implement. Hierarchical data structures however where hard to implement and a none standard format makes it harder to exchange data with a webservice/other programs. So I opted for using JSON as my import/export format.  JSON is alot easier to parse than XML and is still ubiquitous in software developement so I cast aside XML (for now).

You can grab my implementation for reading and writing JSON with CMake  at  https://github.com/toeb/oo-cmake.git.  Its part of my object oriented CMake library and uses my implementation for CMake maps and references.

Note: Because CMake only understands strings the deserializer only accepts string , array or object values.  Also all keys and values have to be double quoted.

As always: feedback is most welcome if you feel like it you can tell me if you find it usefull, have ideas, or think that I have reinvented the wheel.

Here are some examples for serialization and deserialization:

Code Snippet
  1. # serialize empty value
  2. json_serialize(res “”)
  3. assert(NOT res)
  4. # serialze simple value
  5. json_serialize(res “hello!”)
  6. assert(res)
  7. assert(“\”hello!\”” STREQUAL ${res})
  8. #empty object
  9. element(uut MAP)
  10. element(END)
  11. json_serialize(res ${uut})
  12. assert(“{}” STREQUAL ${res})
  13. # empty list
  14. element(uut LIST)
  15. element(END)
  16. json_serialize(res ${uut})
  17. assert(“[]” STREQUAL ${res})
  18. # ref
  19. ref_new(uut)
  20. ref_set(${uut} “a b c”)
  21. json_serialize(res ${uut})
  22. assert(“\”a b c\”” STREQUAL ${res})
  23. # list with one element
  24. element(uut LIST)
  25. value(1)
  26. element(END)
  27. json_serialize(res ${uut})
  28. assert(“[\”1\”]” STREQUAL ${res})
  29. # list with multiple elements element
  30. element(uut LIST)
  31. value(1)
  32. value(2)
  33. element(END)
  34. json_serialize(res ${uut})
  35. assert(“[\”1\”,\”2\”]” STREQUAL ${res})
  36. # object with single value
  37. element(uut MAP)
  38. value(KEY k1 val1)
  39. element(END)
  40. json_serialize(res ${uut})
  41. assert(“{\”k1\”:\”val1\”}” STREQUAL ${res})
  42. # object with multiple value
  43. element(uut MAP)
  44. value(KEY k1 val1)
  45. value(KEY k2 val2)
  46. element(END)
  47. json_serialize(res ${uut})
  48. assert(“{\”k1\”:\”val1\”,\”k2\”:\”val2\”}” STREQUAL ${res})
  49. # list with single map
  50. element(uut LIST)
  51. element()
  52. value(KEY k1 1)
  53. element(END)
  54. element(END)
  55. json_serialize(res ${uut})
  56. assert(“[{\”k1\”:\”1\”}]” STREQUAL ${res})
  57. # list with differnt elements map
  58. element(uut LIST)
  59.     element(MAP)
  60.         value(KEY k1 1)
  61.         value(KEY k2 2)
  62.         value(KEY k3 3)
  63.     element(END)
  64.     element(LIST)
  65.         value(1)
  66.         value(2)
  67.     element(END)
  68.     value(a)
  69.     value(b)
  70. element(END)
  71. json_serialize(res ${uut})
  72. assert(“[{\”k1\”:\”1\”,\”k2\”:\”2\”,\”k3\”:\”3\”},[\”1\”,\”2\”],\”a\”,\”b\”]” STREQUAL ${res})
  73. # deserialize a empty value
  74. json_deserialize(res “”)
  75. assert(NOT res)
  76. # deserialize a empty object
  77. json_deserialize(res “{}”)
  78. assert(res)
  79. ref_isvalid(is_ref ${res} )
  80. assert(is_ref MESSAGE “expected res to be a ref”)
  81. # desirialize a empty array
  82. json_deserialize(res “[]”)
  83. assert(res)
  84. ref_isvalid(is_ref ${res})
  85. assert(is_ref MESSAGE “expected res to be a ref”)
  86. # deserialize a simple value
  87. json_deserialize(res “\”teststring\””)
  88. assert(${res} STREQUAL “teststring”)
  89. # deserialize a array with one value
  90. json_deserialize(res “[\”1\”]”)
  91. map_navigate(${res} val “[0]”)
  92. assert(${val} STREQUAL “1”)
  93. #deserialize a array with multiple values
  94. json_deserialize(res “[\”1\”, \”2\”]”)
  95. map_navigate(${res} val “[0]”)
  96. assert(${val} STREQUAL “1”)
  97. map_navigate(${res} val “[1]”)
  98. assert(${val} STREQUAL “2”)
  99. # deserialize a simple object with one value
  100. json_deserialize(res “{ \”key\” : \”value\”}”)
  101. map_navigate(${res} val “key”)
  102. assert(${val} STREQUAL “value”)
  103. # deserialize a simple object with multiple values
  104. json_deserialize(res “{ \”key\” : \”value\”, \”key2\” : \”val2\”}”)
  105. map_navigate(${res} val “key”)
  106. assert(${val} STREQUAL “value”)
  107. map_navigate(${res} val “key2”)
  108. assert(${val} STREQUAL “val2”)
  109. # deserialize a simple nested structure
  110. json_deserialize(res “{ \”key\” : {\”key3\”:\”myvalue\” }, \”key2\” : \”val2\”}”)
  111. map_navigate(${res} val “key2”)
  112. assert(${val} STREQUAL “val2”)
  113. map_navigate(${res} val “key.key3”)
  114. assert(${val} STREQUAL “myvalue”)
  115. # deserialize a nested structure containing both arrays and objects
  116. json_deserialize(res “{ \”key\” : [\”1\”, \”2\”], \”key2\” : \”val2\”}”)
  117. map_navigate(${res} val “key2”)
  118. assert(${val} STREQUAL “val2”)
  119. map_navigate(${res} val “key[0]”)
  120. assert(${val} STREQUAL “1”)
  121. map_navigate(${res} val “key[1]”)
  122. assert(${val} STREQUAL “2”)
  123. # deserialize a ‘deeply’ nested structure and get a value
  124. json_deserialize(res “{ \”key\” : [{\”k1\”:\”v1\”}, \”2\”], \”key2\” : \”val2\”}”)
  125. map_navigate(${res} val “key[0].k1”)
  126. assert(${val} STREQUAL “v1”)