{"id":18753036,"url":"https://github.com/spotify/spotify-json","last_synced_at":"2025-04-12T17:42:47.372Z","repository":{"id":41176201,"uuid":"69027831","full_name":"spotify/spotify-json","owner":"spotify","description":"Fast and nice to use C++ JSON library.","archived":false,"fork":false,"pushed_at":"2024-11-28T10:13:39.000Z","size":7770,"stargazers_count":202,"open_issues_count":4,"forks_count":42,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-03-27T19:15:13.465Z","etag":null,"topics":["json","json-libraries","json-parser","json-serialization"],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/spotify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-09-23T13:35:41.000Z","updated_at":"2025-03-25T22:45:28.000Z","dependencies_parsed_at":"2024-12-20T21:12:25.678Z","dependency_job_id":"82d1b397-3642-4483-bd39-f7d6107fd450","html_url":"https://github.com/spotify/spotify-json","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/spotify%2Fspotify-json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/spotify","download_url":"https://codeload.github.com/spotify/spotify-json/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247070923,"owners_count":20878586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","json-libraries","json-parser","json-serialization"],"created_at":"2024-11-07T17:23:54.734Z","updated_at":"2025-04-03T20:11:03.192Z","avatar_url":"https://github.com/spotify.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"spotify-json\n============\n\n[![License](https://img.shields.io/github/license/spotify/spotify-json.svg)](LICENSE)\n[![macOS \u0026 Linux Builds](https://img.shields.io/travis/spotify/spotify-json/master.svg?style=flat)](https://travis-ci.org/spotify/spotify-json)\n[![Windows Build](https://ci.appveyor.com/api/projects/status/github/spotify/spotify-json?svg=true)](https://ci.appveyor.com/project/fxb/spotify-json)\n\nA C++17 JSON writer and parser library. It\n\n* parses and serializes directly to and from statically typed C++ objects,\n* requires very little boilerplate code,\n* is fast and makes use of vectorization,\n* supports UTF-8,\n* comes with [a good suite of tests](test),\n* is deployed and in active use on over 250 million devices,\n* and [has API documentation](doc/api.md).\n\nspotify-json depends on [Google's double-conversion library](https://github.com/google/double-conversion),\nwhich must be linked in to the code that uses spotify-json.\n\nExample\n------\n\n```cpp\n#include \u003ciostream\u003e\n#include \u003cmap\u003e\n#include \u003cstring\u003e\n\n#include \u003cspotify/json.hpp\u003e\n\nusing namespace spotify::json;\n\nstruct Track {\n  std::string uri;\n  std::string uid;\n  std::map\u003cstd::string, std::string\u003e metadata;\n};\n\nnamespace spotify {\nnamespace json {\n\n// Specialize spotify::json::default_codec_t to specify default behavior when\n// encoding and decoding objects of certain types.\ntemplate \u003c\u003e\nstruct default_codec_t\u003cTrack\u003e {\n  static object_t\u003cTrack\u003e codec() {\n    auto codec = object\u003cTrack\u003e();\n    codec.required(\"uri\", \u0026Track::uri);\n    codec.optional(\"uid\", \u0026Track::uid);\n    codec.optional(\"metadata\", \u0026Track::metadata);\n    return codec;\n  }\n};\n\n}  // namespace json\n}  // namespace spotify\n\nint main() {\n  const auto parsed_track = decode\u003cTrack\u003e(R\"({ \"uri\": \"spotify:track:xyz\", \"metadata\": { \"a\": \"b\" } })\");\n  std::cout \u003c\u003c \"Parsed track with uri \" \u003c\u003c parsed_track.uri \u003c\u003c std::endl;\n\n  Track track;\n  track.uri = \"spotify:track:abc\";\n  track.uid = \"a-uid\";\n  const auto json = encode(track);\n  std::cout \u003c\u003c \"Encoded the track into \" \u003c\u003c json \u003c\u003c std::endl;\n\n  return 0;\n}\n```\n\nUsage\n-----\n\nspotify-json offers [a range of codec types](doc/api.md#the-codec) that can serialize\nand parse specific JSON values. There are codecs for each of the basic data\ntypes that JSON offers: [strings](doc/api.md#string_t),\n[numbers](doc/api.md#number_t), [arrays](doc/api.md#array_t),\n[booleans](doc/api.md#boolean_t), [objects](doc/api.md#object_t) and\n[null](doc/api.md#null_t).\n\n\n### Constructing and composing codecs\n\nA codec for integers can be made using\n[`codec::number\u003cint\u003e()`](doc/api.md#number_t). The codec for strings can be\ninstantiated with [`codec::string()`](doc/api.md#string_t).\n\nCodecs are composable. It is for example possible to construct a codec for\nparsing and serialization of JSON arrays of numbers, such as `[1,4,2]`:\n[`codec::array\u003cstd::vector\u003cint\u003e\u003e(codec::number\u003cint\u003e())`](doc/api.md#array_t).\n\nConstructing deeply nested codecs manually as above can become tedious. To ease\nthis pain, [`default_codec`](doc/api.md#default_codec_t) is a helper function\nthat makes it easy to construct codecs for built-in types. For example,\n`default_codec\u003cint\u003e()` is a codec that can parse and serialize numbers, and\n`default_codec\u003cstd::vector\u003cint\u003e\u003e()` is one that works on arrays of numbers.\n\nIt is possible to work with JSON objects with arbitrary keys. For example,\n`default_codec\u003cstd::map\u003cstd::string, bool\u003e\u003e()` is a codec for JSON objects\nwith strings as keys and booleans as values.\n\n\n### Parsing and serialization\n\nParsing is done using the [`decode`](doc/api.md#decode)\nfunction:\n\n```cpp\ntry {\n  decode(codec::number\u003cint\u003e(), \"123\") == 123;\n  decode\u003cint\u003e(\"123\") == 123;  // Shortcut for decode(default_codec\u003cint\u003e(), \"123\")\n  decode\u003cstd::vector\u003cint\u003e\u003e(\"[1,2,3]\") == std::vector{ 1, 2, 3 };\n} catch (const decode_exception \u0026e) {\n  std::cout \u003c\u003c \"Failed to decode: \" \u003c\u003c e.what() \u003c\u003c std::endl;\n}\n```\n\n[`decode`](doc/api.md#decode) throws\n[`decode_exception`](doc/api.md#decode_exception) when parsing fails. There is\nalso a function [`try_decode`](doc/api.md#try_decode) that doesn't throw on\nparse errors:\n\n```cpp\nint result = 0;\nif (try_decode(result, \"123\")) {\n  result == 123;\n} else {\n  // Decoding failed!\n}\n```\n\nSimilarly, serialization is done using [`encode`](doc/api.md#encode):\n\n```cpp\nencode(codec::number\u003cint\u003e(), 123) == \"123\";\nencode(123) == \"123\";  // Shortcut for encode(default_codec\u003cint\u003e(), 123)\nencode(std::vector\u003cint\u003e{ 1, 2, 3 }) == \"[1,2,3]\";\n```\n\n### Working with rich objects\n\nWorking with basic types such as numbers, strings, booleans and arrays is all\nnice and dandy, but most practical applications need to deal with rich JSON\nschemas that involve objects.\n\nMany JSON libraries work by parsing JSON strings into a tree structure that can\nbe read by the application. In our experience, this approach often leads to\nlarge amounts of boilerplate code to extract the information in this tree object\ninto statically typed counterparts that are practical to use in C++. This\nboilerplate is painful to write, bug-prone and slow due to unnecessary copying.\nSAX-style event based libraries such as [yajl](http://lloyd.github.io/yajl/)\navoid the slowdown but require even more boilerplate.\n\nspotify-json avoids these issues by parsing the JSON directly into statically\ntyped data structures. To explain how, let's use the example of a basic\ntwo-dimensional coordinate, represented in JSON as `{\"x\":1,\"y\":2}`. In C++, such\na coordinate may be represented as a struct:\n\n```cpp\nstruct Coordinate {\n  Coordinate() = default;\n  Coordinate(int x, int y) : x(x), y(y) {}\n\n  int x = 0;\n  int y = 0;\n};\n```\n\nWith spotify-json, it is possible to construct a codec that can convert\n`Coordinate` directly to and from JSON:\n\n```cpp\nauto coordinate_codec = object\u003cCoordinate\u003e();\ncoordinate_codec.required(\"x\", \u0026Coordinate::x);\ncoordinate_codec.required(\"y\", \u0026Coordinate::y);\n```\n\nThe use of `required` will cause parsing to fail if the fields are missing.\nThere is also an `optional` method. For more information, see\n[`object_t`'s API documentation](https://ghe.spotify.net/spotify-sdk/spotify-json/blob/master/doc/api.md#object_t).\n\nThis codec can be used with `encode` and `decode`:\n\n```cpp\nencode(coordinate_codec, Coordinate(10, 0)) == R\"({\"x\":10,\"y\":0})\";\n\nconst Coordinate coord = decode(coordinate_codec, R\"({ \"x\": 12, \"y\": 13 })\");\ncoord.x == 12;\ncoord.y == 13;\n```\n\nObjects can be nested. To demonstrate this, let's introduce another data type:\n\n```cpp\nstruct Player {\n  std::string name;\n  std::string instrument;\n  Coordinate position;\n};\n```\n\nA codec for `Player` might be created with\n\n```cpp\nauto player_codec = object\u003cPlayer\u003e();\nplayer_codec.required(\"name\", \u0026Player::name);\nplayer_codec.required(\"instrument\", \u0026Player::instrument);\n// Because there is no default_codec for Coordinate, we need to pass in the\n// codec explicitly:\nplayer_codec.required(\"position\", \u0026Player::position, coordinate_codec);\n\n// Let's use it:\nPlayer player;\nplayer.name = \"Daniel\";\nplayer.instrument = \"guitar\";\nencode(player_codec, player) == R\"({\"name\":\"Daniel\",\"instrument\":\"guitar\",\"position\":{\"x\":0,\"y\":0}})\";\n```\n\nSince codecs are just normal objects, it is possible to create and use\nseveral different codecs for any given data type. This makes it possible to\nparameterize parsing and do other fancy things, but for most data types there\nwill only really exist one codec. For these cases, it is possible to extend\nthe `default_codec` helper to support your own data types.\n\n```cpp\nnamespace spotify {\nnamespace json {\n\ntemplate \u003c\u003e\nstruct default_codec_t\u003cCoordinate\u003e {\n  static object_t\u003cCoordinate\u003e codec() {\n    auto codec = object\u003cCoordinate\u003e();\n    codec.required(\"x\", \u0026Coordinate::x);\n    codec.required(\"y\", \u0026Coordinate::y);\n    return codec;\n  }\n};\n\ntemplate \u003c\u003e\nstruct default_codec_t\u003cPlayer\u003e {\n  static object_t\u003cPlayer\u003e codec() {\n    auto codec = object\u003cPlayer\u003e();\n    codec.required(\"name\", \u0026Player::name);\n    codec.required(\"instrument\", \u0026Player::instrument);\n    codec.required(\"position\", \u0026Player::position);\n    return codec;\n  }\n};\n\n}  // namespace json\n}  // namespace spotify\n```\n\n`Coordinate` and `Player` can now be used like any other type that spotify-json\nsupports out of the box:\n\n```cpp\nencode(Coordinate(10, 0)) == R\"({\"x\":10,\"y\":0})\";\ndecode\u003cstd::vector\u003cCoordinate\u003e\u003e(R\"([{ \"x\": 1, \"y\": -1 }])\") == std::vector\u003cCoordinate\u003e{ Coordinate(1, -1) };\n\nPlayer player;\nplayer.name = \"Martin\";\nplayer.instrument = \"drums\";\nencode(player) == R\"({\"name\":\"Martin\",\"instrument\":\"drums\",\"position\":{\"x\":0,\"y\":0}})\";\n```\n\n\n### Advanced usage\n\nThe examples above cover the most commonly used parts of spotify-json. The\nlibrary supports more things that sometimes come in handy:\n\n* Most STL containers, including\n  [`array`, `vector`, `deque`, `list`, `set`, `unordered_set`](doc/api.md#array_t),\n  [`pair`, `tuple`](doc/api.md#tuple_t),\n  [`map` and `unordered_map`](doc/api.md#map_t)\n* [C++ `enum`s and similar types](doc/api.md#enumeration_t)\n* [Arbitrary conversion logic](doc/api.md#transform_t), for example when a\n  raw binary hash in C++ is represented as a hex coded string in JSON\n* [Dealing with versioning](doc/api.md#eq_t)\n* [Ignoring values that are of the wrong type instead of failing the parse](doc/api.md#handling-missing-empty-null-and-invalid-values)\n* Values wrapped in [`unique_ptr`s](doc/api.md#unique_ptr_t) and\n  [`shared_ptr`s](doc/api.md#shared_ptr_t)\n* [`boost::optional`](doc/api.md#optional)\n* [`boost::chrono` and `std::chrono` types](doc/api.md#chrono)\n* [Dealing with virtual classes / type erasure](doc/api.md#cast_t)\n* [Floating point numbers with lossless serialize/parse roundtrip](doc/api.md#number_t)\n\n\n[Detailed API documentation](doc/api.md)\n------------------------------------------\n\n\nLinking against the library in a project\n----------------------------------------\n\nIf your project is built with CMake, it is easy to use spotify-json. Here is an\nexample of how it can be done:\n\n1. Add spotify-json as a git submodule under `vendor/`\n2. Add the following lines to the `CMakeLists.txt` of your project:\n\n```\nadd_subdirectory(vendor/spotify-json)\ntarget_link_libraries([YOUR TARGET] spotify-json)\n```\n\n\nBuilding and running tests\n--------------------------\n### Requirements\n  * CMake ([http://www.cmake.org](http://www.cmake.org/))\n  * Boost ([http://www.boost.org](http://www.boost.org/))\n\n### 1. Make CMake find Boost\n    export BOOST_ROOT=/path/to/boost\n    export BOOST_LIBRARYDIR=/path/to/boost/lib/\n\n### 2. Run CMake\n    mkdir build\n    cd build\n    cmake -G \u003cgenerator-name\u003e ..\n\nRun \"cmake --help\" for a list of generators available on your system.\n\n### 3. Build project with Visual Studio / Xcode / Ninja\n\n### 4. Run CTest\n    cd build\n    ctest -j 8\n\nCode of conduct\n---------------\nThis project adheres to the [Open Code of Conduct][code-of-conduct]. By participating, you are expected to honor this code.\n\n[code-of-conduct]: https://github.com/spotify/code-of-conduct/blob/master/code-of-conduct.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspotify%2Fspotify-json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspotify%2Fspotify-json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspotify%2Fspotify-json/lists"}