7

How to control the serialization format in the boost json library. I am trying to serialize this object and the floats are being output in scientific notation. How to output in fixed notation like 12000000 instead of 1.2E7? And 0 instead of 0E0.

i.e.

{"id":"de69041b-141b-4e01-b349-458f26f08259","price":3.343403E12,"qty":1.2E7}
{"id":"de69041b-141b-4e01-b349-458f26f08259","price":0E0,"qty":0E0}

Here is a minimal program that will output floats in exponential format (ubuntu 20.04, g++ 9.3.0, boost 1.76.0)

#include <iostream>
#include <boost/json/src.hpp>

using namespace std;
namespace bj = boost::json;

int main(void)
{
    bj::object obj1 = {
        {"id", 1},
        {"price", 3343403000000.00},
        {"qty", 13546000000000.00}
    };

    bj::object obj2 = {
        {"id", 2},
        {"price", 0.0},
        {"qty", 0.0}
    };
    cout << "obj1:" << bj::serialize(obj1) << endl;
    cout << "obj2:" << bj::serialize(obj2) << endl;

    return 0;
}

Output:

obj1:{"id":1,"price":3.343403E12,"qty":1.3546E13}
obj2:{"id":2,"price":0E0,"qty":0E0}

2 Answers2

2

To the best of my knowledge that is not a feature. There has been a fair bit of discussion on the boost mailing list when the library was being reviewed prior to acceptance, so if you want you can check the archives for the rationale.

My recollection of it is that the library focuses on a narrow featureset facilitating machine-to-machine transport (99% of JSON, e.g. in restful APIs). That implies a focus on

  • making it correct
  • making it fast

The same thing came up a day or so ago: Is there a way to switch boost::json::serializer to beautified output? (where I quote from the documentation intro section)

sehe
  • 374,641
  • 47
  • 450
  • 633
  • 2
    Thank you sehe! I reached the same conclusion after going through the boost json source. I thought some downstream processes might break due to the very different looking output, but to my surprise the consumers ran just fine as it seems to be 100% compliant json. My initial worry that it is losing double/floating point digits has been laid to rest. After eyeballing some output it seems that it is preserving all the significant digits. – user16141266 Jun 24 '21 at 12:12
  • 1
    This was a learning process for me, too. I hit some JSON extraction exceptions that I was convinced were caused by the exponential notation. Testing more, I found that the exponential notation was parsed and serialized perfectly. Thanks for the question and the answer. I'm very happy boost finally took on the huge need for JSON processing. nhlohmann::json library was great but it's nice to have something "more official" and peer-reviewed, etc. – moodboom Sep 13 '21 at 15:44
1

The only thing I can think of is to hack on the existing PrettyPrint example, and modifying the double output section to change the formatting.

  case json::kind::double_:
    os << jv.get_double();
    break;

This question showed how to do it The Old Way, as well as something new in C++20:

Add some stream formatting to taste:

  #include <iomanip>

  case json::kind::double_:
    os << std::fixed << std::setw(10) << std::setprecision(5)
       << jv.get_double();
    break;

or the new-fangled

  case json::kind::double_:
    os << std::format("{:10.5}", jv.get_double());
    break;
Mark Storer
  • 15,672
  • 3
  • 42
  • 80