aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetri Lehtinen <petri@digip.org>2013-06-11 22:23:40 -0700
committerPetri Lehtinen <petri@digip.org>2013-06-11 22:23:40 -0700
commit8d439710cd73aef868227092b5c4865720cd66dd (patch)
tree1f7626c8d489857bdd11cb31bd8e916359e8bbf5
parent018f7fea315e6695fa9bd16036ebc50a1506322c (diff)
parent120a90a155b1db062eb984be53381f65a698e0e4 (diff)
downloadjansson-8d439710cd73aef868227092b5c4865720cd66dd.zip
jansson-8d439710cd73aef868227092b5c4865720cd66dd.tar.gz
jansson-8d439710cd73aef868227092b5c4865720cd66dd.tar.bz2
Merge pull request #123 from jjwchoy/decode-ignore-int
Implemented a decode option to only decode numbers to reals
-rw-r--r--doc/apiref.rst10
-rw-r--r--doc/conformance.rst5
-rw-r--r--src/jansson.h7
-rw-r--r--src/load.c11
-rw-r--r--test/suites/api/test_load.c23
5 files changed, 51 insertions, 5 deletions
diff --git a/doc/apiref.rst b/doc/apiref.rst
index 198c0c2..d92fb3b 100644
--- a/doc/apiref.rst
+++ b/doc/apiref.rst
@@ -950,6 +950,16 @@ macros can be ORed together to obtain *flags*.
.. versionadded:: 2.1
+``JSON_DECODE_INT_AS_REAL``
+ JSON defines only one number type. Jansson distinguishes between
+ ints and reals. For more information see :ref:`real-vs-integer`.
+ With this flag enabled the decoder interprets all numbers as real
+ values. Integers that do not have an exact double representation
+ will silently result in a loss of precision. Integers that cause
+ a double overflow will cause an error.
+
+ .. versionadded:: 2.5
+
Each function also takes an optional :type:`json_error_t` parameter
that is filled with error information if decoding fails. It's also
updated on success; the number of bytes of input read is written to
diff --git a/doc/conformance.rst b/doc/conformance.rst
index 6f4c929..19f603d 100644
--- a/doc/conformance.rst
+++ b/doc/conformance.rst
@@ -38,6 +38,8 @@ strings.
Numbers
=======
+.. _real-vs-integer:
+
Real vs. Integer
----------------
@@ -51,7 +53,8 @@ A JSON number is considered to be a real number if its lexical
representation includes one of ``e``, ``E``, or ``.``; regardless if
its actual numeric value is a true integer (e.g., all of ``1E6``,
``3.0``, ``400E-2``, and ``3.14E3`` are mathematical integers, but
-will be treated as real values).
+will be treated as real values). With the ``JSON_DECODE_INT_AS_REAL``
+decoder flag set all numbers are interpreted as real.
All other JSON numbers are considered integers.
diff --git a/src/jansson.h b/src/jansson.h
index 77cc5ba..d441fcf 100644
--- a/src/jansson.h
+++ b/src/jansson.h
@@ -236,9 +236,10 @@ json_t *json_deep_copy(json_t *value);
/* decoding */
-#define JSON_REJECT_DUPLICATES 0x1
-#define JSON_DISABLE_EOF_CHECK 0x2
-#define JSON_DECODE_ANY 0x4
+#define JSON_REJECT_DUPLICATES 0x1
+#define JSON_DISABLE_EOF_CHECK 0x2
+#define JSON_DECODE_ANY 0x4
+#define JSON_DECODE_INT_AS_REAL 0x8
typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data);
diff --git a/src/load.c b/src/load.c
index 1eb3be4..b671892 100644
--- a/src/load.c
+++ b/src/load.c
@@ -775,6 +775,7 @@ error:
static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
{
json_t *json;
+ double value;
switch(lex->token) {
case TOKEN_STRING: {
@@ -783,7 +784,15 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error)
}
case TOKEN_INTEGER: {
- json = json_integer(lex->value.integer);
+ if (flags & JSON_DECODE_INT_AS_REAL) {
+ if(jsonp_strtod(&lex->saved_text, &value)) {
+ error_set(error, lex, "real number overflow");
+ return NULL;
+ }
+ json = json_real(value);
+ } else {
+ json = json_integer(lex->value.integer);
+ }
break;
}
diff --git a/test/suites/api/test_load.c b/test/suites/api/test_load.c
index 30ba65c..6eddb34 100644
--- a/test/suites/api/test_load.c
+++ b/test/suites/api/test_load.c
@@ -87,6 +87,28 @@ static void decode_any()
json_decref(json);
}
+static void decode_int_as_real()
+{
+ json_t *json;
+ json_error_t error;
+
+ // This number cannot be represented exactly by a double
+ const char *imprecise = "9007199254740993";
+ json_int_t expected = 9007199254740992ll;
+
+ json = json_loads("42", JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY, &error);
+ if (!json || !json_is_real(json) || json_real_value(json) != 42.0)
+ fail("json_load decode int as real failed - int");
+ json_decref(json);
+
+ // Tests that large numbers are handled correctly
+ json = json_loads(imprecise, JSON_DECODE_INT_AS_REAL | JSON_DECODE_ANY,
+ &error);
+ if (!json || !json_is_real(json) || expected != json_real_value(json))
+ fail("json_load decode int as real failed - expected imprecision");
+ json_decref(json);
+}
+
static void load_wrong_args()
{
json_t *json;
@@ -132,6 +154,7 @@ static void run_tests()
reject_duplicates();
disable_eof_check();
decode_any();
+ decode_int_as_real();
load_wrong_args();
position();
}