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 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 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; 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 << '{'; out << '{';
if (! allOnOneLine) if (! allOnOneLine)
@@ -107,7 +107,7 @@ void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const
out << '"'; out << '"';
JSONFormatter::writeString (out, properties.getName (i)); JSONFormatter::writeString (out, properties.getName (i));
out << "\": "; 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) 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 never need to call it directly, but it's virtual so that custom object types
can stringify themselves appropriately. can stringify themselves appropriately.
*/ */
virtual void writeAsJSON (OutputStream&, int indentLevel, bool allOnOneLine);
virtual void writeAsJSON (OutputStream&, int indentLevel, bool allOnOneLine, int maximumDecimalPlaces);
private: private:
//============================================================================== //==============================================================================
NamedValueSet properties; NamedValueSet properties;
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE #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) {} virtual void invokeMethod (const Identifier&, const var*, int) {}
#endif #endif


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

@@ -323,7 +323,8 @@ class JSONFormatter
{ {
public: public:
static void write (OutputStream& out, const var& v, 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()) if (v.isString())
{ {
@@ -343,14 +344,18 @@ public:
{ {
out << (static_cast<bool> (v) ? "true" : "false"); out << (static_cast<bool> (v) ? "true" : "false");
} }
else if (v.isDouble())
{
out << String (static_cast<double> (v), maximumDecimalPlaces);
}
else if (v.isArray()) else if (v.isArray())
{ {
writeArray (out, *v.getArray(), indentLevel, allOnOneLine);
writeArray (out, *v.getArray(), indentLevel, allOnOneLine, maximumDecimalPlaces);
} }
else if (v.isObject()) else if (v.isObject())
{ {
if (DynamicObject* object = v.getDynamicObject()) if (DynamicObject* object = v.getDynamicObject())
object->writeAsJSON (out, indentLevel, allOnOneLine);
object->writeAsJSON (out, indentLevel, allOnOneLine, maximumDecimalPlaces);
else else
jassertfalse; // Only DynamicObjects can be converted to JSON! jassertfalse; // Only DynamicObjects can be converted to JSON!
} }
@@ -420,7 +425,8 @@ public:
} }
static void writeArray (OutputStream& out, const Array<var>& array, static void writeArray (OutputStream& out, const Array<var>& array,
const int indentLevel, const bool allOnOneLine)
const int indentLevel, const bool allOnOneLine,
int maximumDecimalPlaces)
{ {
out << '['; out << '[';
@@ -434,7 +440,7 @@ public:
if (! allOnOneLine) if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize); 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) if (i < array.size() - 1)
{ {
@@ -493,16 +499,16 @@ Result JSON::parse (const String& text, var& result)
return JSONParser::parseObjectOrArray (text.getCharPointer(), 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); MemoryOutputStream mo (1024);
JSONFormatter::write (mo, data, 0, allOnOneLine);
JSONFormatter::write (mo, data, 0, allOnOneLine, maximumDecimalPlaces);
return mo.toUTF8(); 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) 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. /** 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 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. 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 @see writeToStream
*/ */
static String toString (const var& objectToFormat, 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. /** Parses a string that was created with the toString() method.
This is slightly different to the parse() methods because they will reject primitive 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. /** 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 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. 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 @see toString
*/ */
static void writeToStream (OutputStream& output, static void writeToStream (OutputStream& output,
const var& objectToFormat, const var& objectToFormat,
bool allOnOneLine = false);
bool allOnOneLine = false,
int maximumDecimalPlaces = 20);
/** Returns a version of a string with any extended characters escaped. */ /** Returns a version of a string with any extended characters escaped. */
static String escapeString (StringRef); 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); } 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; out << "function " << functionCode;
} }


Loading…
Cancel
Save