3

Is there a way to control the output precision in JSON generated using rapidjson?

For example:

writer.String("length");
writer.Double(1.0 / 3.0);

This generates something like:

{ length: 0.33333333 }

I'm sending a lot of values and only need two decimal places for several values.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • It looks like this isn't possible. I've opened a [feature request](https://code.google.com/p/rapidjson/issues/detail?id=67) for this functionality. – Drew Noakes Apr 19 '13 at 14:09

2 Answers2

7

From sources

Writer& Double(double d)
{ 
   Prefix(kNumberType);
   WriteDouble(d);
   return *this; 
}

//! \todo Optimization with custom double-to-string converter.
void WriteDouble(double d) {
        char buffer[100];
#if _MSC_VER
    int ret = sprintf_s(buffer, sizeof(buffer), "%g", d);
#else
    int ret = snprintf(buffer, sizeof(buffer), "%g", d);
#endif
    RAPIDJSON_ASSERT(ret >= 1);
    for (int i = 0; i < ret; i++)
         stream_.Put(buffer[i]);
}

For the g conversion style conversion with style e or f will be performed.

f: Precision specifies the minimum number of digits to appear after the decimal point character. The default precision is 6.

quotes from here

There is variant, to write new Writer class and write your own Double function realisation.

Simple example of last case

template<typename Stream>
class Writer : public rapidjson::Writer<Stream>
{
public:
   Writer(Stream& stream) : rapidjson::Writer<Stream>(stream)
   {
   }
   Writer& Double(double d)
   {
      this->Prefix(rapidjson::kNumberType);
      char buffer[100];
      int ret = snprintf(buffer, sizeof(buffer), "%.2f", d);
      RAPIDJSON_ASSERT(ret >= 1);
      for (int i = 0; i < ret; ++i)
         this->stream_.Put(buffer[i]);
      return *this;
   }
};

usage like

int main()
{
   const std::string json =
      "{"
      "\"string\": 0.3221"
      "}";
   rapidjson::Document doc;
   doc.Parse<0>(json.c_str());

   rapidjson::FileStream fs(stdout);
   Writer<rapidjson::FileStream> writer(fs);
   doc.Accept(writer);
}

result: {"string":0.32}

Of course if you use Writer manually, you can writer function Double with precision parameter.

ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • Thanks. Looks like it's not natively possible then. I'm happy to add an overload into their API though, so will make one based on your suggestions. – Drew Noakes Apr 19 '13 at 13:46
3

For anyone stumbling onto this case, this method was added to rapidjson on Feb 11, 2016:

rapidjson::Writer::SetMaxDecimalPlaces(int maxDecimalPlaces)

The provided default Writer class is more complete than the other answer here, and should always be used, unless you have very specific needs.

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
ncore
  • 46
  • 1