Browse Source

JSON: Added the ability to limit the number of decimal places when serialising floating point numbers

tags/2021-05-28
tpoole 8 years ago
parent
commit
5b6e482a0d
6 changed files with 54 additions and 16 deletions
  1. +28
    -0
      BREAKING-CHANGES.txt
  2. +2
    -2
      modules/juce_core/containers/juce_DynamicObject.cpp
  3. +2
    -2
      modules/juce_core/containers/juce_DynamicObject.h
  4. +15
    -9
      modules/juce_core/javascript/juce_JSON.cpp
  5. +6
    -2
      modules/juce_core/javascript/juce_JSON.h
  6. +1
    -1
      modules/juce_core/javascript/juce_Javascript.cpp

+ 28
- 0
BREAKING-CHANGES.txt View File

@@ -1,6 +1,34 @@
JUCE breaking changes
=====================

Develop Branch
=============

Change
------
The writeAsJSON virtual method of the DynamicObject class requires an
additional parameter, maximumDecimalPlaces, to specify the maximum precision of
floating point numbers.

Possible Issues
---------------
Classes which inherit from DynamicObject and override this method will need to
update their method signature.

Workaround
----------
Your custom DynamicObject class can choose to ignore the additional parameter
if you don't wish to support this behaviour.

Rationale
---------
When serialising the results of calculations to JSON the rounding of floating
point numbers can result in numbers with 17 significant figures where only a
few are required. This change to DynamicObject is required to support
truncating those numbers.



Version 5.1.0
=============



+ 2
- 2
modules/juce_core/containers/juce_DynamicObject.cpp View File

@@ -91,7 +91,7 @@ DynamicObject::Ptr DynamicObject::clone()
return d;
}
void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine)
void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine, int maximumDecimalPlaces)
{
out << '{';
if (! allOnOneLine)
@@ -107,7 +107,7 @@ void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const
out << '"';
JSONFormatter::writeString (out, properties.getName (i));
out << "\": ";
JSONFormatter::write (out, properties.getValueAt (i), indentLevel + JSONFormatter::indentSize, allOnOneLine);
JSONFormatter::write (out, properties.getValueAt (i), indentLevel + JSONFormatter::indentSize, allOnOneLine, maximumDecimalPlaces);
if (i < numValues - 1)
{


+ 2
- 2
modules/juce_core/containers/juce_DynamicObject.h View File

@@ -113,14 +113,14 @@ public:
never need to call it directly, but it's virtual so that custom object types
can stringify themselves appropriately.
*/
virtual void writeAsJSON (OutputStream&, int indentLevel, bool allOnOneLine);
virtual void writeAsJSON (OutputStream&, int indentLevel, bool allOnOneLine, int maximumDecimalPlaces);
private:
//==============================================================================
NamedValueSet properties;
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// These methods have been deprecated - use var::invoke instead
// This method has been deprecated - use var::invoke instead
virtual void invokeMethod (const Identifier&, const var*, int) {}
#endif


+ 15
- 9
modules/juce_core/javascript/juce_JSON.cpp View File

@@ -323,7 +323,8 @@ class JSONFormatter
{
public:
static void write (OutputStream& out, const var& v,
const int indentLevel, const bool allOnOneLine)
const int indentLevel, const bool allOnOneLine,
int maximumDecimalPlaces)
{
if (v.isString())
{
@@ -343,14 +344,18 @@ public:
{
out << (static_cast<bool> (v) ? "true" : "false");
}
else if (v.isDouble())
{
out << String (static_cast<double> (v), maximumDecimalPlaces);
}
else if (v.isArray())
{
writeArray (out, *v.getArray(), indentLevel, allOnOneLine);
writeArray (out, *v.getArray(), indentLevel, allOnOneLine, maximumDecimalPlaces);
}
else if (v.isObject())
{
if (DynamicObject* object = v.getDynamicObject())
object->writeAsJSON (out, indentLevel, allOnOneLine);
object->writeAsJSON (out, indentLevel, allOnOneLine, maximumDecimalPlaces);
else
jassertfalse; // Only DynamicObjects can be converted to JSON!
}
@@ -420,7 +425,8 @@ public:
}
static void writeArray (OutputStream& out, const Array<var>& array,
const int indentLevel, const bool allOnOneLine)
const int indentLevel, const bool allOnOneLine,
int maximumDecimalPlaces)
{
out << '[';
@@ -434,7 +440,7 @@ public:
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine, maximumDecimalPlaces);
if (i < array.size() - 1)
{
@@ -493,16 +499,16 @@ Result JSON::parse (const String& text, var& result)
return JSONParser::parseObjectOrArray (text.getCharPointer(), result);
}
String JSON::toString (const var& data, const bool allOnOneLine)
String JSON::toString (const var& data, const bool allOnOneLine, int maximumDecimalPlaces)
{
MemoryOutputStream mo (1024);
JSONFormatter::write (mo, data, 0, allOnOneLine);
JSONFormatter::write (mo, data, 0, allOnOneLine, maximumDecimalPlaces);
return mo.toUTF8();
}
void JSON::writeToStream (OutputStream& output, const var& data, const bool allOnOneLine)
void JSON::writeToStream (OutputStream& output, const var& data, const bool allOnOneLine, int maximumDecimalPlaces)
{
JSONFormatter::write (output, data, 0, allOnOneLine);
JSONFormatter::write (output, data, 0, allOnOneLine, maximumDecimalPlaces);
}
String JSON::escapeString (StringRef s)


+ 6
- 2
modules/juce_core/javascript/juce_JSON.h View File

@@ -90,10 +90,12 @@ public:
/** Returns a string which contains a JSON-formatted representation of the var object.
If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format.
The maximumDecimalPlaces parameter determines the precision of floating point numbers.
@see writeToStream
*/
static String toString (const var& objectToFormat,
bool allOnOneLine = false);
bool allOnOneLine = false,
int maximumDecimalPlaces = 20);
/** Parses a string that was created with the toString() method.
This is slightly different to the parse() methods because they will reject primitive
@@ -105,11 +107,13 @@ public:
/** Writes a JSON-formatted representation of the var object to the given stream.
If allOnOneLine is true, the result will be compacted into a single line of text
with no carriage-returns. If false, it will be laid-out in a more human-readable format.
The maximumDecimalPlaces parameter determines the precision of floating point numbers.
@see toString
*/
static void writeToStream (OutputStream& output,
const var& objectToFormat,
bool allOnOneLine = false);
bool allOnOneLine = false,
int maximumDecimalPlaces = 20);
/** Returns a version of a string with any extended characters escaped. */
static String escapeString (StringRef);


+ 1
- 1
modules/juce_core/javascript/juce_Javascript.cpp View File

@@ -827,7 +827,7 @@ struct JavascriptEngine::RootObject : public DynamicObject
DynamicObject::Ptr clone() override { return new FunctionObject (*this); }
void writeAsJSON (OutputStream& out, int /*indentLevel*/, bool /*allOnOneLine*/) override
void writeAsJSON (OutputStream& out, int /*indentLevel*/, bool /*allOnOneLine*/, int /*maximumDecimalPlaces*/) override
{
out << "function " << functionCode;
}


Loading…
Cancel
Save