Skip to content

Commit 324fe89

Browse files
authored
Adding better error messages for JSON parsing errors (#75)
* Adding better error messages for JSON parsing. * Updating exception message.
1 parent 1e0c3fd commit 324fe89

File tree

5 files changed

+204
-16
lines changed

5 files changed

+204
-16
lines changed

olcut-config-json/src/main/java/com/oracle/labs/mlrg/olcut/config/json/JsonLoader.java

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -291,20 +291,26 @@ protected void parseComponent(ObjectNode node) {
291291
while (listElementItr.hasNext()) {
292292
Entry<String, JsonNode> elementEntry = listElementItr.next();
293293
String elementName = elementEntry.getKey();
294-
switch (elementName) {
295-
case ConfigLoader.ITEM:
296-
listOutput.add(new SimpleProperty(elementEntry.getValue().textValue()));
297-
break;
298-
case ConfigLoader.TYPE:
299-
try {
300-
classListOutput.add(Class.forName(elementEntry.getValue().textValue()));
301-
} catch (ClassNotFoundException cnfe) {
302-
throw new ConfigLoaderException("Unable to find class "
303-
+ elementEntry.getValue().textValue() + " in component " + curComponent + ", propertylist " + propName);
304-
}
305-
break;
306-
default:
307-
throw new ConfigLoaderException("Unknown node in component " + curComponent + ", propertylist " + propName + ", node = " + e.getValue().toString());
294+
if (elementEntry.getValue().isTextual()) {
295+
String value = elementEntry.getValue().textValue();
296+
switch (elementName) {
297+
case ConfigLoader.ITEM:
298+
listOutput.add(new SimpleProperty(value));
299+
break;
300+
case ConfigLoader.TYPE:
301+
try {
302+
classListOutput.add(Class.forName(value));
303+
} catch (ClassNotFoundException cnfe) {
304+
throw new ConfigLoaderException("Unable to find class "
305+
+ value + " in component " + curComponent + ", propertylist " + propName);
306+
}
307+
break;
308+
default:
309+
throw new ConfigLoaderException("Unknown node in component " + curComponent + ", propertylist " + propName + ", node = " + e.getValue().toString());
310+
}
311+
} else {
312+
throw new ConfigLoaderException("Invalid value in component " + curComponent + ", propertylist " + propName + ", node = " + e.getValue().toString() + "" +
313+
", all OLCUT property list values must be strings, other types are not parsed.");
308314
}
309315
}
310316
}
@@ -324,13 +330,19 @@ protected void parseComponent(ObjectNode node) {
324330
if (mapEntry.getValue().isTextual()) {
325331
mapOutput.put(mapEntry.getKey(), new SimpleProperty(mapEntry.getValue().textValue()));
326332
} else {
327-
throw new ConfigLoaderException("Unknown node in component " + curComponent + ", propertymap " + propName + ", node = " + e.getValue().toString());
333+
throw new ConfigLoaderException("Invalid value in component " + curComponent + ", propertymap " + propName + ", node = " + e.getValue().toString() +
334+
", all OLCUT property map values must be strings, other types are not parsed.");
328335
}
329336
}
330337
rpd.add(propName, new MapProperty(mapOutput));
331338
} else {
332339
// Generic property.
333-
rpd.add(propName, new SimpleProperty(e.getValue().textValue()));
340+
if (e.getValue().isTextual()) {
341+
rpd.add(propName, new SimpleProperty(e.getValue().textValue()));
342+
} else {
343+
throw new ConfigLoaderException("Invalid value in component " + curComponent + ", property " + propName + ", node = " + e.getValue().toString() +
344+
", all OLCUT property values must be strings, other types are not parsed.");
345+
}
334346
}
335347
}
336348
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates.
3+
*
4+
* Licensed under the 2-clause BSD license.
5+
*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* 1. Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
*
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
*/
28+
29+
package com.oracle.labs.mlrg.olcut.config.json.test;
30+
31+
import com.oracle.labs.mlrg.olcut.config.ConfigurationManager;
32+
import com.oracle.labs.mlrg.olcut.config.io.ConfigLoaderException;
33+
import com.oracle.labs.mlrg.olcut.config.json.JsonConfigFactory;
34+
import org.junit.jupiter.api.Assertions;
35+
import org.junit.jupiter.api.BeforeAll;
36+
import org.junit.jupiter.api.Test;
37+
38+
import java.io.IOException;
39+
40+
import static com.oracle.labs.mlrg.olcut.config.ConfigurationManager.createModuleResourceString;
41+
import static org.junit.jupiter.api.Assertions.fail;
42+
43+
public class TypeCheckingTest {
44+
45+
@BeforeAll
46+
public static void setUp() {
47+
ConfigurationManager.addFileFormatFactory(new JsonConfigFactory());
48+
}
49+
50+
@Test
51+
public void arrayTest() throws IOException {
52+
try {
53+
ConfigurationManager cm = new ConfigurationManager(createModuleResourceString(this.getClass(), "typeCheckingListConfig.json"));
54+
fail("Should have thrown ConfigLoaderException");
55+
} catch (ConfigLoaderException e) {
56+
Assertions.assertTrue(e.getMessage().startsWith("Invalid value"));
57+
}
58+
}
59+
60+
@Test
61+
public void propertyTest() throws IOException {
62+
try {
63+
ConfigurationManager cm = new ConfigurationManager(createModuleResourceString(this.getClass(), "typeCheckingPropertyConfig.json"));
64+
fail("Should have thrown ConfigLoaderException");
65+
} catch (ConfigLoaderException e) {
66+
Assertions.assertTrue(e.getMessage().startsWith("Invalid value"));
67+
}
68+
}
69+
70+
@Test
71+
public void mapTest() throws IOException {
72+
try {
73+
ConfigurationManager cm = new ConfigurationManager(createModuleResourceString(this.getClass(), "typeCheckingMapConfig.json"));
74+
fail("Should have thrown ConfigLoaderException");
75+
} catch (ConfigLoaderException e) {
76+
Assertions.assertTrue(e.getMessage().startsWith("Invalid value"));
77+
}
78+
}
79+
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"config" : {
3+
"global-properties" : { },
4+
"components" : [ {
5+
"name" : "a",
6+
"type" : "com.oracle.labs.mlrg.olcut.test.config.ArrayConfigurable",
7+
"export" : "false",
8+
"import" : "false",
9+
"properties" : {
10+
"floatArray" : [ {
11+
"item" : "1.1f"
12+
}, {
13+
"item" : "2.3"
14+
}, {
15+
"item" : "3.5"
16+
} ],
17+
"doubleArray" : [ {
18+
"item" : 1e-16
19+
}, {
20+
"item" : 2e-16
21+
}, {
22+
"item" : "3.16"
23+
} ],
24+
"longArray" : [ {
25+
"item" : 9223372036854775807
26+
}, {
27+
"item" : "9223372036854775806"
28+
}, {
29+
"item" : "5"
30+
} ],
31+
"byteArray" : [ {
32+
"item" : "1"
33+
}, {
34+
"item" : "2"
35+
}, {
36+
"item" : "3"
37+
} ],
38+
"shortArray" : [ {
39+
"item" : "1"
40+
}, {
41+
"item" : "2"
42+
}, {
43+
"item" : "3"
44+
} ],
45+
"intArray" : [ {
46+
"item" : 1
47+
}, {
48+
"item" : 2
49+
}, {
50+
"item": "3"
51+
} ],
52+
"charArray" : [ {
53+
"item" : "a"
54+
}, {
55+
"item" : "b"
56+
}, {
57+
"item" : "c"
58+
} ]
59+
}
60+
} ]
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"config" : {
3+
"components" : [ {
4+
"name" : "mapTest",
5+
"type" : "com.oracle.labs.mlrg.olcut.test.config.MapConfigurable",
6+
"export" : "false",
7+
"import" : "false",
8+
"properties" : {
9+
"map" : {
10+
"foo" : "quux",
11+
"things" : 5
12+
}
13+
}
14+
} ]
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"config": {
3+
"global-properties": {},
4+
"components": [
5+
{
6+
"name": "a",
7+
"type": "com.oracle.labs.mlrg.olcut.test.config.BasicConfigurable",
8+
"export": "false",
9+
"import": "false",
10+
"properties": {
11+
"s": "one",
12+
"d": 3.0,
13+
"i": 2
14+
}
15+
}
16+
]
17+
}
18+
}

0 commit comments

Comments
 (0)