JSON в чистом Си
Какую библиотеку посоветуете для работы с json в чистом Си? Гугл сходу выдает json-c и jansson. Какая лучше? Или искать третью?
Зачем чистый С? Может рассмотреть альтернативы? Или специфические требования?
подписался, тоже хотелось бы услышать «за» и «против».
Я использовал json-c. Но с ней поосторожней надо: течь может.
В общем, если тебе серьезно надо, то лучше свое напиши. Все равно тебе ведь не нужно общую поддержку! Только частную же.
Скажем, в другой утилитке, формирующей JSON-файл, я вообще никаких библиотек не использовал (т.к. сформировать JSON файл можно и ручками на бумажке).
Eddy, а мне вот кажется что jansson вполне вменяемый, и писать свое нет смысла. документация приятная, сборка простая (просто все C-файлы вкинуть в проект), и т.п.
Вполне возможно. Просто когда я выбирал, jansson вообще был никакой.
По-диагонали глянул API jansson — вроде бы те же яйца, что и json-c.
Кстати, можно вообще на макросах или своей прокладке реализовать поддержку обеих. И в зависимости от того, что у юзера установлено, cmake будет активировать те или иные макросы. Если ни той, ни другой — сообщать об ошибке.
ну если тебе такое нужно — то так и делай. я просто нужные либы в проект включаю.
Может, не совсем релевантно к вопросу ОПа, но все же спрошу здесь — а есть ли профит использовать json в качестве формата конфигурационных файлов в проектах на с и с++? Недавно возникал вопрос о том, какой простенький язык для описания иерархических структур выбрать. Пока что остановились на б-гомерзком yaml-e, но поскольку решение было написано на коленке в качестве временной затычки, есть шанс, что вскоре этот вопрос поднимется снова.
Json мне сердцу милее, но смущает то, что формат не предусматривает комментариев внутри файла.
Я обычно для себя делаю, поэтому чаще всего мне лень. Если я где-то делаю зачатки «универсальности», то лишь оттого, что нужно бывает запускать код и на древнем железе.
Смотря что за конфиги у тебя. Мне за глаза хватает «ini-формата» (типа «переменная=значение»), а еще бинарными конфигами пользуюсь, если нет нужды вручную их править. JSON нужен лишь в случае сложных структур данных.
А jansson не может течь? Внешне то оно неплохо выглядит, но могут быть подводные камни.
не знаю. я не пользовался пока.
а есть ли профит использовать json в качестве формата конфигурационных файлов в проектах на с и с++? Недавно возникал вопрос о том, какой простенький язык для описания иерархических структур выбрать.
если хватает json, то json, иначе xml
а есть ли профит использовать json в качестве формата конфигурационных файлов в проектах на с и с++?
однозначно есть. я накостылил свой велосипед, и уже давно жалею. с json было бы меньше проблем.
Источник
Json c library linux
libjson — simple and efficient json parser and printer in C
libjson is a simple library without any dependancies to parse and pretty print the JSON format (RFC 4627). The JSON format is a concise and structured data format.
- interruptible parser: append data to the state how you want it.
- No object model integrated
- Small codebase: handcoded parser and efficient factorisation make the code smalls and perfect for embedding.
- Fast: use efficient code and small parsing tables for maximum efficiency.
- Full JSON support.
- UTF8 validation of the input.
- No number conversion: user convert data the way they want.
- Secure: optional limits on nesting level, and on data size.
- Optional comments: in YAML/python style and C style.
- Optional user defined allocation functions.
libjson parser is an interruptible handcoded state parse. the parser takes character or string as input. Since it’s interruptible, it’s up to the user to feed the stream to the parser, which permits complete flexibility as to whether the data is coming from a pipe, a network socket, a file on disk, a serial line, or crafted by the user.
The parser doesn’t create an object tree for you, but each time it comes up with an element in this data, it just callback to the user with the type found and for some type, the data associated with it. It can be compared to the SAX way of XML, hence it’s called SAJ (Simple API for JSon).
The parser doesn’t convert number to any native C format, but instead callback with a string that is a valid JSon number. JSon number can be of any size, so that’s up to user to decide whetever or not, the number can map to native C type int32_t, int64_t, or a complex integer type. As well the user has a choice to refuse the integer at the callback stage if the length is not appropriate.
The parser optionally allows YAML and/or C comments to be ignored if the config structure is set accordingly, otherwise a JSON_ERROR_COMMENT_NOT_ALLOWED is returned.
Embedding & Build system
The primary use case of this pieces of code is providing JSON capability to your program or library, without adding an extra build dependency. You can add it to your project directly, and integrate it without any fuss.
The «build system» available with the library is just a way to test that everything in the library conforms to specifications and features. It’s not necessarily intended as a way to build portable dynamic library (.so or .dll). It should works in simple case of building on Linux and BSDs though.
For others use (eg. windows, OS X, obscure unixes), it is much simpler to integrate the library in your program or library directly.
Simple build fixes to build on more platforms will be accepted though.
Open a pull request with your new feature, simple code fix, or documentation fixes. Please conform to coding style, and to the spirit of the library: policy is not imposed by the library.
The parser API is really simple, totaling only 5 API calls:
- json_parser_init
- json_parser_char
- json_parser_string
- json_parser_is_done
- json_parser_free
json_parser_init initializes a new parser context from a parser config and takes a callback + userdata. This callback function is used everything the parser need to communicate a type and value to the client side of the library.
json_parser_char take one character and inject it in the parser. on parsing success it will return a 0 value, but on parsing error it returns a parsing error that represents the type of the error encounters. see JSON_ERROR_* for the full set of return values.
json_parser_string is similar to json_parser_char except that it takes a string and a length. it also returns the number of character processed, which is useful when an parser error happened in the stream to pinpoint where.
json_parser_is_done permits to test whetever or not the parser is in a terminated state. it involves not beeing into any structure.
json_parser_free is the opposite of init, it just free the allocated structure.
The Printer API
the printer API is simple too:
- json_printer_init
- json_printer_free
- json_printer_pretty
- json_printer_raw
json_printer_init initialise a printing context and takes a callback + userdata that will be called for every character that the printer wants to output. the caller can have the printer callback redirect to anything it wants.
json_printer_free is the opposite of init
json_printer_raw takes a json type and an optional data and length value depending on the type. it’s up to the caller to verify that the order of type are JSON-compliant, otherwise the generated document won’t be able to be parsed again.
json_printer_pretty works like json_printer_raw but is targetted for human reading by appending newlines and spaces
Jsonlint utility program
jsonlint utility provided with the library to verify, or reformat json stream. also useful as example on how to use the library.
About
a JSON parser and printer library in C. easy to integrate with any model.
Источник
Json c library linux
JSON-C — A JSON implementation in C
JSON-C implements a reference counting object model that allows you to easily construct JSON objects in C, output them as JSON formatted strings and parse JSON formatted strings back into the C representation of JSON objects. It aims to conform to RFC 7159.
Building on Unix with git , gcc and cmake
gcc , clang , or another C compiler
cmake>=2.8 , >=3.16 recommended, cmake=>3.1 for tests
To generate docs you’ll also need:
If you are on a relatively modern system, you’ll likely be able to install the prerequisites using your OS’s packaging system.
Install using apt (e.g. Ubuntu 16.04.2 LTS)
Note: it’s also possible to put your build directory inside the json-c source directory, or even not use a separate build directory at all, but certain things might not work quite right (notably, make distcheck )
Generating documentation with Doxygen:
The library documentation can be generated directly from the source code using Doxygen tool:
The json-c library is built with CMake, which can take a few options.
Variable | Type | Description |
---|---|---|
CMAKE_INSTALL_PREFIX | String | The install location. |
CMAKE_BUILD_TYPE | String | Defaults to «debug». |
BUILD_SHARED_LIBS | Bool | The default build generates a dynamic (dll/so) library. Set this to OFF to create a static library only. |
BUILD_STATIC_LIBS | Bool | The default build generates a static (lib/a) library. Set this to OFF to create a shared library only. |
DISABLE_STATIC_FPIC | Bool | The default builds position independent code. Set this to OFF to create a shared library only. |
DISABLE_BSYMBOLIC | Bool | Disable use of -Bsymbolic-functions. |
DISABLE_THREAD_LOCAL_STORAGE | Bool | Disable use of Thread-Local Storage (HAVE___THREAD). |
DISABLE_WERROR | Bool | Disable use of -Werror. |
ENABLE_RDRAND | Bool | Enable RDRAND Hardware RNG Hash Seed. |
ENABLE_THREADING | Bool | Enable partial threading support. |
OVERRIDE_GET_RANDOM_SEED | String | A block of code to use instead of the default implementation of json_c_get_random_seed(), e.g. on embedded platforms where not even the fallback to time() works. Must be a single line. |
Pass these options as -D on CMake’s command-line.
Building with partial threading support
Although json-c does not support fully multi-threaded access to object trees, it has some code to help make its use in threaded programs a bit safer. Currently, this is limited to using atomic operations for json_object_get() and json_object_put().
Since this may have a performance impact, of at least 3x slower according to https://stackoverflow.com/a/11609063, it is disabled by default. You may turn it on by adjusting your cmake command with: -DENABLE_THREADING=ON
Separately, the default hash function used for object field keys, lh_char_hash, uses a compare-and-swap operation to ensure the random seed is only generated once. Because this is a one-time operation, it is always compiled in when the compare-and-swap operation is available.
cmake-configure wrapper script
For those familiar with the old autoconf/autogen.sh/configure method, there is a cmake-configure wrapper script to ease the transition to cmake.
cmake-configure can take a few options.
options | Description |
---|---|
prefix=PREFIX | install architecture-independent files in PREFIX |
enable-threading | Enable code to support partly multi-threaded use |
enable-rdrand | Enable RDRAND Hardware RNG Hash Seed generation on supported x86/x64 platforms. |
enable-shared | build shared libraries [default=yes] |
enable-static | build static libraries [default=yes] |
disable-Bsymbolic | Avoid linking with -Bsymbolic-function |
disable-werror | Avoid treating compiler warnings as fatal errors |
By default, if valgrind is available running tests uses it. That can slow the tests down considerably, so to disable it use:
To run tests a separate build directory is recommended:
If a test fails, check Testing/Temporary/LastTest.log , tests/testSubDir/$
and check the log files again.
Building on Unix and Windows with vcpkg
You can download and install JSON-C using the vcpkg dependency manager:
The JSON-C port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.
Linking to libjson-c
If your system has pkgconfig , then you can just add this to your makefile :
Without pkgconfig , you would do something like this:
To use json-c you can either include json.h, or preferrably, one of the following more specific header files:
The primary type in json-c is json_object. It describes a reference counted tree of json objects which are created by either parsing text with a json_tokener (i.e. json_tokener_parse_ex() ), or by creating (with json_object_new_object() , json_object_new_int() , etc. ) and adding (with json_object_object_add() , json_object_array_add() , etc. ) them individually. Typically, every object in the tree will have one reference, from its parent. When you are done with the tree of objects, you call json_object_put() on just the root object to free it, which recurses down through any child objects calling json_object_put() on each one of those in turn.
You can get a reference to a single child ( json_object_object_get() or json_object_array_get_idx() ) and use that object as long as its parent is valid.
If you need a child object to live longer than its parent, you can increment the child’s refcount ( json_object_get() ) to allow it to survive the parent being freed or it being removed from its parent ( json_object_object_del() or json_object_array_del_idx() )
When parsing text, the json_tokener object is independent from the json_object that it returns. It can be allocated ( json_tokener_new() ) used one or multiple times ( json_tokener_parse_ex() , and freed ( json_tokener_free() ) while the json_object objects live on.
A json_object tree can be serialized back into a string with json_object_to_json_string_ext() . The string that is returned is only valid until the next «to_json_string» call on that same object. Also, it is freed when the json_object is freed.
Источник