From 630652b8612b65916acfc0e404c430329b1904cd Mon Sep 17 00:00:00 2001 From: Andrew Smithson Date: Tue, 19 Nov 2024 16:43:05 +0000 Subject: [PATCH 1/6] Fail on duplicate tags in object Signed-off-by: Andrew Smithson --- .../java/com/ibm/json/java/JSONObject.java | 1 + .../java/com/ibm/json4j/DuplicateTagTest.java | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/java/com/ibm/json4j/DuplicateTagTest.java diff --git a/src/main/java/com/ibm/json/java/JSONObject.java b/src/main/java/com/ibm/json/java/JSONObject.java index 4fe14cd..d55041a 100644 --- a/src/main/java/com/ibm/json/java/JSONObject.java +++ b/src/main/java/com/ibm/json/java/JSONObject.java @@ -235,6 +235,7 @@ public Object put(Object key, Object value) { if (null == key) throw new IllegalArgumentException("key must not be null"); if (!(key instanceof String)) throw new IllegalArgumentException("key must be a String"); + if (get(key) != null) throw new IllegalArgumentException("duplicate key"); if (!isValidObject(value)) { diff --git a/src/test/java/com/ibm/json4j/DuplicateTagTest.java b/src/test/java/com/ibm/json4j/DuplicateTagTest.java new file mode 100644 index 0000000..631d542 --- /dev/null +++ b/src/test/java/com/ibm/json4j/DuplicateTagTest.java @@ -0,0 +1,26 @@ +package com.ibm.json4j; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.IOException; + +import org.junit.Test; + +import com.ibm.json.java.JSONObject; + +public class DuplicateTagTest { + + @Test + public void testDuplicateId() throws IOException { + String inputJson = "{\"duplicate\": 123, \"duplicate\": 456}"; + + try { + JSONObject obj = JSONObject.parse(inputJson); + fail("Exception should have been thrown"); + } catch (IllegalArgumentException e) { + assertEquals("duplicate key", e.getMessage()); + } + } + +} From baa506f163db302d660b900170c8209403018369 Mon Sep 17 00:00:00 2001 From: Andrew Smithson Date: Wed, 20 Nov 2024 13:08:56 +0000 Subject: [PATCH 2/6] Add tag name to error Signed-off-by: Andrew Smithson --- src/main/java/com/ibm/json/java/JSONObject.java | 2 +- src/test/java/com/ibm/json4j/DuplicateTagTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/ibm/json/java/JSONObject.java b/src/main/java/com/ibm/json/java/JSONObject.java index d55041a..902e493 100644 --- a/src/main/java/com/ibm/json/java/JSONObject.java +++ b/src/main/java/com/ibm/json/java/JSONObject.java @@ -235,7 +235,7 @@ public Object put(Object key, Object value) { if (null == key) throw new IllegalArgumentException("key must not be null"); if (!(key instanceof String)) throw new IllegalArgumentException("key must be a String"); - if (get(key) != null) throw new IllegalArgumentException("duplicate key"); + if (get(key) != null) throw new IllegalArgumentException("duplicate key \'" + key + "\'"); if (!isValidObject(value)) { diff --git a/src/test/java/com/ibm/json4j/DuplicateTagTest.java b/src/test/java/com/ibm/json4j/DuplicateTagTest.java index 631d542..d9ed3b8 100644 --- a/src/test/java/com/ibm/json4j/DuplicateTagTest.java +++ b/src/test/java/com/ibm/json4j/DuplicateTagTest.java @@ -19,7 +19,7 @@ public void testDuplicateId() throws IOException { JSONObject obj = JSONObject.parse(inputJson); fail("Exception should have been thrown"); } catch (IllegalArgumentException e) { - assertEquals("duplicate key", e.getMessage()); + assertEquals("duplicate key \'duplicate\'", e.getMessage()); } } From 8ff5515bdac8b5e4b5005b29e854176502e2beb1 Mon Sep 17 00:00:00 2001 From: Andrew Smithson Date: Thu, 21 Nov 2024 09:13:13 +0000 Subject: [PATCH 3/6] Undo previous duplicate check Signed-off-by: Andrew Smithson --- src/main/java/com/ibm/json/java/JSONObject.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/ibm/json/java/JSONObject.java b/src/main/java/com/ibm/json/java/JSONObject.java index 902e493..4fe14cd 100644 --- a/src/main/java/com/ibm/json/java/JSONObject.java +++ b/src/main/java/com/ibm/json/java/JSONObject.java @@ -235,7 +235,6 @@ public Object put(Object key, Object value) { if (null == key) throw new IllegalArgumentException("key must not be null"); if (!(key instanceof String)) throw new IllegalArgumentException("key must be a String"); - if (get(key) != null) throw new IllegalArgumentException("duplicate key \'" + key + "\'"); if (!isValidObject(value)) { From 64a4b9598b27d83991aafc956e1d2adf8f1e75ba Mon Sep 17 00:00:00 2001 From: Andrew Smithson Date: Thu, 21 Nov 2024 09:41:20 +0000 Subject: [PATCH 4/6] Add duplicate protection during parsing Signed-off-by: Andrew Smithson --- src/main/java/com/ibm/json/java/JSONObject.java | 5 +++++ src/main/java/com/ibm/json/java/internal/Parser.java | 11 +++++++++++ src/test/java/com/ibm/json4j/DuplicateTagTest.java | 6 +++--- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/ibm/json/java/JSONObject.java b/src/main/java/com/ibm/json/java/JSONObject.java index 4fe14cd..a0369e1 100644 --- a/src/main/java/com/ibm/json/java/JSONObject.java +++ b/src/main/java/com/ibm/json/java/JSONObject.java @@ -113,6 +113,11 @@ static public JSONObject parse(InputStream is) throws IOException { return parse(isr); } + static public JSONObject parse(String str, boolean duplicateProtection) throws IOException { + StringReader strReader = new StringReader(str); + return new Parser(strReader, duplicateProtection).parse(); + } + /** * Create a new instance of this class. diff --git a/src/main/java/com/ibm/json/java/internal/Parser.java b/src/main/java/com/ibm/json/java/internal/Parser.java index d180243..b590228 100644 --- a/src/main/java/com/ibm/json/java/internal/Parser.java +++ b/src/main/java/com/ibm/json/java/internal/Parser.java @@ -26,6 +26,7 @@ public class Parser private Tokenizer tokenizer; private Token lastToken; + private boolean duplicateProtection; /** * Contructor @@ -39,6 +40,11 @@ public Parser(Reader reader) throws IOException { this.tokenizer = new Tokenizer(reader); } + public Parser(Reader reader, boolean duplicateProtection) throws IOException { + this.tokenizer = new Tokenizer(reader); + this.duplicateProtection = duplicateProtection; + } + /** * Method to initiate the parse of the toplevel JSON object, which will in turn parse all child JSON objects contained within. * Same as calling parse(false); @@ -111,6 +117,11 @@ public JSONObject parseObject(boolean ordered) throws IOException { lastToken = tokenizer.next(); Object val = parseValue(ordered); + if (duplicateProtection) { + if (result.get(key) != null) { + throw new IOException("Duplicate Key \'" + key + "\'"); + } + } result.put(key, val); if (lastToken == Token.TokenComma) diff --git a/src/test/java/com/ibm/json4j/DuplicateTagTest.java b/src/test/java/com/ibm/json4j/DuplicateTagTest.java index d9ed3b8..9de14db 100644 --- a/src/test/java/com/ibm/json4j/DuplicateTagTest.java +++ b/src/test/java/com/ibm/json4j/DuplicateTagTest.java @@ -16,10 +16,10 @@ public void testDuplicateId() throws IOException { String inputJson = "{\"duplicate\": 123, \"duplicate\": 456}"; try { - JSONObject obj = JSONObject.parse(inputJson); + JSONObject obj = JSONObject.parse(inputJson, true); fail("Exception should have been thrown"); - } catch (IllegalArgumentException e) { - assertEquals("duplicate key \'duplicate\'", e.getMessage()); + } catch (IOException e) { + assertEquals("Duplicate Key \'duplicate\'", e.getMessage()); } } From 8911f03822ffb04861ec07b9414740eb0736ae08 Mon Sep 17 00:00:00 2001 From: Andrew Smithson Date: Thu, 21 Nov 2024 14:40:30 +0000 Subject: [PATCH 5/6] Add duplicate protection to OrderedJSONObject Signed-off-by: Andrew Smithson --- src/main/java/com/ibm/json/java/OrderedJSONObject.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/ibm/json/java/OrderedJSONObject.java b/src/main/java/com/ibm/json/java/OrderedJSONObject.java index 5a18c4c..4e1cd95 100644 --- a/src/main/java/com/ibm/json/java/OrderedJSONObject.java +++ b/src/main/java/com/ibm/json/java/OrderedJSONObject.java @@ -99,6 +99,11 @@ static public JSONObject parse(InputStream is) throws IOException { return parse(isr); } + static public JSONObject parse(String str, boolean duplicateProtection) throws IOException { + StringReader strReader = new StringReader(str); + return new Parser(strReader, duplicateProtection).parse(true); + } + /** * Method to put a JSON'able object into the instance. Note that the order of initial puts controls the order of serialization. * Meaning that the first time an item is put into the object determines is position of serialization. Subsequent puts with the same From 3cc35d34b10f24fa0341580e53a2fd3b45ffe251 Mon Sep 17 00:00:00 2001 From: Andrew Smithson Date: Fri, 22 Nov 2024 08:53:32 +0000 Subject: [PATCH 6/6] Add JavaDoc Signed-off-by: Andrew Smithson --- src/main/java/com/ibm/json/java/JSONObject.java | 8 ++++++++ src/main/java/com/ibm/json/java/OrderedJSONObject.java | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/main/java/com/ibm/json/java/JSONObject.java b/src/main/java/com/ibm/json/java/JSONObject.java index a0369e1..e3a7f69 100644 --- a/src/main/java/com/ibm/json/java/JSONObject.java +++ b/src/main/java/com/ibm/json/java/JSONObject.java @@ -113,6 +113,14 @@ static public JSONObject parse(InputStream is) throws IOException { return parse(isr); } + /** + * Convert a String of JSON text into object form. + * @param str The JSON string to parse into a Java Object. + * @param duplicateProtection Whether having duplicate keys in an object will throw an error + * @return The contructed JSON Object. + * + * @throws IOEXception Thrown if malformed JSON is read, + */ static public JSONObject parse(String str, boolean duplicateProtection) throws IOException { StringReader strReader = new StringReader(str); return new Parser(strReader, duplicateProtection).parse(); diff --git a/src/main/java/com/ibm/json/java/OrderedJSONObject.java b/src/main/java/com/ibm/json/java/OrderedJSONObject.java index 4e1cd95..9d0ae0e 100644 --- a/src/main/java/com/ibm/json/java/OrderedJSONObject.java +++ b/src/main/java/com/ibm/json/java/OrderedJSONObject.java @@ -99,6 +99,14 @@ static public JSONObject parse(InputStream is) throws IOException { return parse(isr); } + /** + * Convert a String of JSON text into object form. + * @param str The JSON string to parse into a Java Object. + * @param duplicateProtection Whether having duplicate keys in an object will throw an error + * @return The contructed JSON Object. Note that the JSONObject will be an instance of OrderedJSONObject and as such, attribute order is maintained. + * + * @throws IOEXception Thrown if malformed JSON is read, + */ static public JSONObject parse(String str, boolean duplicateProtection) throws IOException { StringReader strReader = new StringReader(str); return new Parser(strReader, duplicateProtection).parse(true);