Skip to content

Commit cd7491c

Browse files
author
jiachengzhuo
committed
Implement Milestone 3: add keyTransformer support
1 parent 4f14d9b commit cd7491c

File tree

2 files changed

+119
-11
lines changed

2 files changed

+119
-11
lines changed

src/main/java/org/json/XML.java

Lines changed: 90 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import java.math.BigInteger;
1111
import java.util.*;
1212
import java.io.BufferedReader;
13-
import java.io.Reader;
13+
import java.util.function.Function;
1414
import java.util.stream.Collectors;
1515

1616
/**
@@ -484,7 +484,10 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
484484
}
485485

486486
// overwritten method of parse which allows to pass a prefix tag
487-
private static boolean parse(XMLTokener x, JSONObject context, String name, String prefix, XMLParserConfiguration config, int currentNestingDepth)
487+
/* Milestone3
488+
overwritten new method of parse
489+
*/
490+
private static boolean parseMilestone3(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, int currentNestingDepth,Function<String, String> keyTransformer)
488491
throws JSONException {
489492
char c;
490493
int i;
@@ -567,6 +570,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
567570

568571
} else {
569572
tagName = (String) token;
573+
String transformedTagName = keyTransformer.apply(tagName);//add
570574
token = null;
571575
jsonObject = new JSONObject();
572576
boolean nilAttributeFound = false;
@@ -584,7 +588,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
584588
if (!(token instanceof String)) {
585589
throw x.syntaxError("Missing value");
586590
}
587-
591+
String transformedKey = keyTransformer.apply(string); //add new code
588592
if (config.isConvertNilAttributeToNull()
589593
&& NULL_ATTR.equals(string)
590594
&& Boolean.parseBoolean((String) token)) {
@@ -593,6 +597,14 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
593597
&& TYPE_ATTR.equals(string)) {
594598
xmlXsiTypeConverter = config.getXsiTypeMap().get(token);
595599
} else if (!nilAttributeFound) {
600+
Object obj = stringToValue((String) token);
601+
jsonObject.accumulate(transformedKey, obj);
602+
}
603+
token = null;
604+
} else {
605+
jsonObject.accumulate(keyTransformer.apply(string), "");
606+
}
607+
/*} else if (!nilAttributeFound) {
596608
Object obj = stringToValue((String) token);
597609
if (obj instanceof Boolean) {
598610
jsonObject.accumulate(prefix + string,
@@ -612,13 +624,33 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
612624
} else {
613625
jsonObject.accumulate(prefix + string, "");
614626
}
627+
*/
615628

616629

617630
} else if (token == SLASH) {
618631
// Empty tag <.../>
619632
if (x.nextToken() != GT) {
620633
throw x.syntaxError("Misshaped tag");
621634
}
635+
if (config.getForceList().contains(tagName)) {
636+
if (nilAttributeFound) {
637+
context.append(transformedTagName, JSONObject.NULL);
638+
} else if (jsonObject.length() > 0) {
639+
context.append(transformedTagName, jsonObject);
640+
} else {
641+
context.put(transformedTagName, new JSONArray());
642+
}
643+
} else {
644+
if (nilAttributeFound) {
645+
context.accumulate(transformedTagName, JSONObject.NULL);
646+
} else if (jsonObject.length() > 0) {
647+
context.accumulate(transformedTagName, jsonObject);
648+
} else {
649+
context.accumulate(transformedTagName, "");
650+
}
651+
}
652+
return false;
653+
/*
622654
if (config.getForceList().contains(prefix + tagName)) {
623655
// Force the value to be an array
624656
if (nilAttributeFound) {
@@ -638,7 +670,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
638670
}
639671
}
640672
return false;
641-
673+
*/
642674
} else if (token == GT) {
643675
// Content, between <...> and </...>
644676
for (;;) {
@@ -673,7 +705,41 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
673705
}
674706

675707
} else if (token == LT) {
708+
if (parseMilestone3(x, jsonObject,tagName, config, currentNestingDepth + 1, keyTransformer)) {
709+
if (config.getForceList().contains(tagName)) {
710+
if (jsonObject.length() == 0) {
711+
context.put(transformedTagName, new JSONArray());
712+
} else if (jsonObject.length() == 1
713+
&& jsonObject.opt(config.getcDataTagName()) != null) {
714+
context.append(transformedTagName, jsonObject.opt(config.getcDataTagName()));
715+
} else {
716+
context.append(transformedTagName, jsonObject);
717+
}
718+
} else {
719+
if (jsonObject.length() == 0) {
720+
context.accumulate(transformedTagName, "");
721+
} else if (jsonObject.length() == 1
722+
&& jsonObject.opt(config.getcDataTagName()) != null) {
723+
context.accumulate(transformedTagName, jsonObject.opt(config.getcDataTagName()));
724+
} else {
725+
context.accumulate(transformedTagName, jsonObject);
726+
}
727+
}
728+
return false;
729+
}
730+
}
731+
}
732+
} else {
733+
throw x.syntaxError("Misshaped tag");
734+
}
735+
}
736+
}
737+
}
738+
}
739+
740+
676741
// Nested element
742+
/*
677743
if (currentNestingDepth == config.getMaxNestingDepth()) {
678744
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
679745
}
@@ -713,6 +779,8 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, Stri
713779
}
714780
}
715781
}
782+
783+
*/
716784
/**
717785
* This method removes any JSON entry which has the key set by XMLParserConfiguration.cDataTagName
718786
* and contains whitespace as this is caused by whitespace between tags. See test XMLTest.testNestedWithWhitespaceTrimmingDisabled.
@@ -1188,11 +1256,24 @@ public static JSONObject toJSONObject(Reader reader, JSONPointer path) throws JS
11881256

11891257
/**
11901258
* Given a customized function, convert the keys in the Json Object
1191-
* @param reader
1192-
* @param prefix
1193-
* @return
1194-
* @throws JSONException
1259+
* @param reader the XML input
1260+
* @param keyTransformer a function that transforms each key name
1261+
* @return JSONObject with transformed keys
1262+
* @throws JSONException if any XML parsing or transformation fails
11951263
*/
1264+
public static JSONObject toJSONObject(Reader reader, Function<String, String> keyTransformer) throws JSONException {
1265+
JSONObject result = new JSONObject();
1266+
XMLTokener x = new XMLTokener(reader);
1267+
1268+
while (x.more()) {
1269+
x.skipPast("<");
1270+
if (x.more()) {
1271+
XML.parseMilestone3(x, result, null, XMLParserConfiguration.ORIGINAL, 0, keyTransformer);
1272+
}
1273+
}
1274+
return result;
1275+
}
1276+
/*
11961277
public static JSONObject toJSONObject(Reader reader, String prefix) throws JSONException {
11971278
JSONObject jo = new JSONObject();
11981279
XMLParserConfiguration config = XMLParserConfiguration.ORIGINAL;
@@ -1205,7 +1286,7 @@ public static JSONObject toJSONObject(Reader reader, String prefix) throws JSONE
12051286
}
12061287
return jo;
12071288
}
1208-
1289+
*/
12091290
/**
12101291
* Helper method: skip the current element and its entire subtree without
12111292
* building any JSON output.
@@ -1868,7 +1949,6 @@ public static JSONObject toJSONObject(Reader reader, JSONPointer path, JSONObjec
18681949
}
18691950
}
18701951

1871-
18721952
/**
18731953
* Convert a well-formed (but not necessarily valid) XML string into a
18741954
* JSONObject. Some information may be lost in this transformation because

src/test/java/org/json/junit/milestone3/tests/XMLKeyTransformerTest.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,40 @@
77
import org.junit.Test;
88

99
import java.io.StringReader;
10+
import java.util.function.Function;
1011

1112
import static org.junit.Assert.assertEquals;
1213

1314
public class XMLKeyTransformerTest {
1415
// define some customized functions for testing
16+
@Test
17+
public void keyTransformerSimpleTest() {
18+
String xml = "<book><title>Title</title><author>John</author></book>";
19+
Function<String, String> prefixer = key -> "swe262_" + key;
20+
21+
JSONObject result = XML.toJSONObject(new StringReader(xml), prefixer);
22+
23+
assertEquals("Title", result.getJSONObject("swe262_book").get("swe262_title"));
24+
assertEquals("John", result.getJSONObject("swe262_book").get("swe262_author"));
25+
}
1526

27+
@Test
28+
public void keyTransformerReverseTest() {
29+
String xml = "<data><item>value</item></data>";
30+
Function<String, String> reverser = key -> new StringBuilder(key).reverse().toString();
31+
32+
JSONObject result = XML.toJSONObject(new StringReader(xml), reverser);
33+
34+
assertEquals("value", result.getJSONObject("atad").get("meti"));
35+
}
36+
37+
@Test(expected = NullPointerException.class)
38+
public void nullReaderTest() {
39+
XML.toJSONObject(null, key -> "x_" + key);
40+
}
41+
}
42+
43+
/*
1644
@Test
1745
public void testXML01() {
1846
String xml = "<book><title><content>Old Title</content></title><author>John</author></book>";
@@ -43,5 +71,5 @@ public void testXML02() {
4371
}
4472
}
4573
}
46-
74+
*/
4775

0 commit comments

Comments
 (0)