Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to format {} in a json string using fmt?

Tags:

c++

json

fmt

I am trying to format a JSON string avoiding using fmt::format because json does include {0}'s and fmt cannot distinguish JSON's bracket from format specifier {0}'s brackets. If use fmt::format i get the following error:

terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  invalid format string
Aborted (core dumped)

This is why I try and use fmt::sprintf. I could not find a helpful solution for c++ but i've seen a Golang solution but it did not work which is: fmt.Sprintf("%[2]d %[1]d\n", 11, 22) (of course I've changed it to fmt::sprintf).

How can I give argument index to a format specifier using fmt::sprintf?

Thanks in advance.

EDIT:

JSONs are not generated by me but sqlite. That json includes a {0} and it is not being formatted because of the outer JSON braces.

like image 536
no more sigsegv Avatar asked Oct 24 '25 17:10

no more sigsegv


2 Answers

std::string json = fmt::format("{{ \"key\": [{}, {}] }}", 42, 17);
std::cout << json << std::endl; // prints { "key": [17, 42] }

Demo: https://godbolt.org/z/4KjTPq4T5

The convention fmt chose for escaping curly brackets is {{ and }}. A backslash, e.g. \{, won't work. While it's common to see double bracketing for string interpolation, e.g. {{ some_var }}, the use of double bracketing as an escape sequence is somewhat unique to cpp (see cppformat).

like image 195
D.Deriso Avatar answered Oct 26 '25 08:10

D.Deriso


I sometimes use fmt to format small JSON snippets too. The other comments about the pitfalls of doing this are valid, but sometimes it's not a critical component and it gets the job done.

From the fmt documentation:

https://fmt.dev/latest/api.html#printf-api

The header fmt/printf.h provides printf-like formatting functionality. The following functions use printf format string syntax with the POSIX extension for positional arguments

That positional argument extension is described here:

https://en.wikipedia.org/wiki/Printf_format_string#Parameter_field

You can %n$... instead of %..., with n repaced with the argument you'd like to use.

For example:

std::string json = fmt::sprintf(R"({ "key": [%2$d, %1$d] })", 42, 17);
std::cout << json << std::endl; // prints { "key": [17, 42] }

Demo: https://godbolt.org/z/9dd734hxG

like image 22
parktomatomi Avatar answered Oct 26 '25 07:10

parktomatomi