Skip to content
/ printj Public

JSON serialization library for c99 using printf-style formatting

Notifications You must be signed in to change notification settings

raph5/printj

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 

Repository files navigation

Printj

JSON serialization library for C using printf-style formatting

Synopsis

#include "printj.h"

int64_t printj(const char *format, ...);
int64_t fprintj(FILE *stream, const char *format, ...);
int64_t snprintj(char *str, size_t size, const char *format, ...);
int64_t asprintj(char **ret, const char *format, ...);

int64_t vprintj(const char *format, va_list args);
int64_t vfprintj(FILE *stream, const char *format, va_list args);
int64_t vsnprintj(char *str, size_t size, const char *format, va_list args);
int64_t vasprintj(char **ret, const char *format, va_list args);

Description

printj is a C99 header-only library for JSON serialization using a simplified printf-like format string.

This library does not support JSON parsing. It is intended for direct, formatted emission of valid JSON. Serialization is done without heap memory allocation, except when using asprintj or vasprintj.

The format string describes a JSON structure and contains directives introduced by a percent sign (%). Quotes around object keys are added automatically.

String values are quoted and escaped automatically. Quotes (") and backslashes (\) inside strings are escaped as required by the JSON specification.

Embedded null characters (\0) are not supported. All strings must be null-terminated. Wide character types are not supported. UTF-8 strings are supported and compatible.

Each function returns the number of characters that would have been written, excluding the terminating null byte, or a negative value on error.

printj() writes to stdout.

fprintj() writes to the given FILE * stream.

snprintj() writes at most size bytes (including the terminating null byte) to the provided buffer.

asprintj() allocates a new null-terminated string using malloc and stores its address in *ret.

The corresponding v* versions accept a va_list instead of variadic arguments.

Format String

The format of a directive is:

%[precision][n][length]specifier

Specifiers

The following specifiers are available:

Specifier Description
b Boolean.
d Signed integer.
u Unsigned integer.
f Floating-point value.
s Null-terminated string.
% Literal percent character. Prints %

The specifier defines the broad type of directive. Though some specifiers can map to different C types. For example, an integer can be represented in C by a short, a long... To clearly define the C type of a directive we use the Length Modifier

Nullable Modifier

If n is appended to a directive, the argument is treated as a pointer to the corresponding type. If the pointer is NULL, the JSON literal null is emitted instead of a value.

int *age_ptr = NULL;
printj("{\"age\":%nd}", age_ptr); // prints {"age":null}

char *name = NULL;
printj("{\"name\":%ns}", name); // prints {"name":null}

Length Modifiers

The length modifier defines the C type that is passed as argument to the directive.

Length b d u f
(none) int int unsigned int double
hh char char unsigned char
h short short unsigned short
l long long unsigned long float
ll long long long long unsigned long long double
z size_t
j intmax_t uintmax_t
t ptrdiff_t

Non-standard modifiers such as Q and Z (capital Z) are not supported. The L length modifier corresponding to long double is also not supported.

Precision

The precision modifier specify the maximum length of the decimal part when serializing floats (or doubles). The default value is 15. For more details about float serialization see Float serialization below.

This modifier is only compatible with the f specifier and will produce an error when applied to any other specifier.

Float Serialization

The floating-point serialization algorithm is based upon this excellent article. It takes doubles as input and eventual float inputs will automatically be converted to doubles. It uses scientific notation on numbers less than 1e-3 or greater or equal to 1e9. The maximum number of digits in the decimal part is set via the precision modifier (see Precision). The default and maximum value of this parameter for doubles is 15. For floats the default precision is 8 (to recognized as a float, your directive must have the appropriate Length Modifier). NaN and infinity are not part of the JSON standard and will be serialized as null.

Rounding is applied to the decimal part so that you can expect loss in precision less than 1/2 * 10^p (where p is the precision modifier). Though due to inherent floating point roundoff errors, when working with precision of 15 or 14 it's possible to get precision loss exceeding 1/2 * 10^p. No precision loss exceeding 10^p was observed during the testing of over 1000000 random doubles.

Installation

This library is distributed as a single header file.

To use the library, define the implementation macro in one C file before including the header:

#define PRINTJ_IMPLEMENTATION
#include "printj.h"

Then include the header wherever needed:

#include "printj.h"

By default, stdio.h is required. To disable all stdio.h usage, define the macro PRINTJ_DONT_USE_STDIO before #including the library. The only required standard headers are stddef.h and stdarg.h.

Similarly you can define PRINTJ_ASSERT, PRINTJ_MALLOC, PRINTJ_REALLOC and PRINTJ_FREE macros by custom assert and malloc implementations.

The current implementation only works on 64-bit systems. Though it could easily be ported to other architectures.

Limitations

  • No validation of JSON output.
  • Strings must not contain embedded null (\0) characters.
  • No bounds-checking of format strings.
  • No validation of UTF-8 input. UTF-8 is assumed to be well-formed.
  • Wide character types (wchar_t, wint_t) are not supported.
  • long double type not supported.
  • Quotes are added automatically around string values and keys.
  • No support for JSON parsing.

Security

This library has not been audited for security. No security review or testing has been performed. Use in security-critical contexts is discouraged without further analysis.

About

JSON serialization library for c99 using printf-style formatting

Resources

Stars

Watchers

Forks

Packages

No packages published