Skip to content

Added method U.fileJsonToXml(jsonFileName, xmlFileName, identStep) #733

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/main/java/com/github/underscore/U.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -2816,6 +2817,39 @@ public static void streamXmlToJson(InputStream xmlInputStream, OutputStream json
streamXmlToJson(xmlInputStream, jsonOutputStream, Json.JsonStringBuilder.Step.TWO_SPACES);
}

public static void fileJsonToXml(
String jsonFileName, String xmlFileName, Xml.XmlStringBuilder.Step identStep)
throws IOException {
final byte[] bytes = Files.readAllBytes(Paths.get(jsonFileName));
String jsonText = new String(removeBom(bytes), detectEncoding(bytes));
Object result = U.fromJson(jsonText);
Path xmlFilePath = Paths.get(xmlFileName);
String lineSeparator = System.lineSeparator();
if (result instanceof Map) {
if (((Map) result).containsKey("#encoding")) {
String encoding = String.valueOf(((Map) result).get("#encoding"));
Files.write(
xmlFilePath,
formatString(Xml.toXml((Map) result, identStep), lineSeparator)
.getBytes(encoding));
} else {
Files.write(
xmlFilePath,
formatString(Xml.toXml((Map) result, identStep), lineSeparator)
.getBytes(StandardCharsets.UTF_8));
}
} else {
Files.write(
xmlFilePath,
formatString(Xml.toXml((List) result, identStep), lineSeparator)
.getBytes(StandardCharsets.UTF_8));
}
}

public static void fileJsonToXml(String jsonFileName, String xmlFileName) throws IOException {
fileJsonToXml(jsonFileName, xmlFileName, Xml.XmlStringBuilder.Step.TWO_SPACES);
}

public static byte[] removeBom(byte[] bytes) {
if ((bytes.length >= 3) && (bytes[0] == -17) && (bytes[1] == -69) && (bytes[2] == -65)) {
return Arrays.copyOfRange(bytes, 3, bytes.length);
Expand Down Expand Up @@ -2848,8 +2882,6 @@ public static String detectEncoding(byte[] buffer) {
encoding = "UnicodeBigUnmarked";
break;
case 0xFFFE0000:
encoding = "UTF_32LE";
break;
case 0x3C000000:
encoding = "UTF_32LE";
break;
Expand Down
93 changes: 83 additions & 10 deletions src/test/java/com/github/underscore/UnderscoreTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,7 @@ void testStreamXmlToJson_validXml_writesJson() throws IOException {
InputStream xmlStream = new ByteArrayInputStream(xml.getBytes());
ByteArrayOutputStream jsonStream = new ByteArrayOutputStream();
U.streamXmlToJson(xmlStream, jsonStream);
String jsonOutput = jsonStream.toString("UTF-8");
String jsonOutput = jsonStream.toString(StandardCharsets.UTF_8);
assertTrue(jsonOutput.contains("name"), "JSON output should contain 'name' field.");
assertTrue(jsonOutput.contains("Test"), "JSON output should contain 'Test' value.");
assertTrue(jsonOutput.startsWith("{"), "JSON output should start with '{'.");
Expand All @@ -1117,10 +1117,11 @@ void testStreamXmlToJson_emptyInput_producesEmptyOrError() {
Exception exception =
assertThrows(
Exception.class,
() -> {
U.streamXmlToJson(
xmlStream, jsonStream, Json.JsonStringBuilder.Step.TWO_SPACES);
},
() ->
U.streamXmlToJson(
xmlStream,
jsonStream,
Json.JsonStringBuilder.Step.TWO_SPACES),
"Should throw exception for empty input.");
String msg = exception.getMessage();
assertNotNull(msg, "Exception message should not be null.");
Expand All @@ -1135,10 +1136,11 @@ void testStreamXmlToJson_invalidXml_throwsException() {
Exception exception =
assertThrows(
Exception.class,
() -> {
U.streamXmlToJson(
xmlStream, jsonStream, Json.JsonStringBuilder.Step.TWO_SPACES);
},
() ->
U.streamXmlToJson(
xmlStream,
jsonStream,
Json.JsonStringBuilder.Step.TWO_SPACES),
"Should throw exception for invalid XML.");
String msg = exception.getMessage();
assertNotNull(msg, "Exception message for invalid XML should not be null.");
Expand All @@ -1150,7 +1152,78 @@ void testStreamXmlToJson_withIndentSteps_producesIndentedJson() throws IOExcepti
InputStream xmlStream = new ByteArrayInputStream(xml.getBytes());
ByteArrayOutputStream jsonStream = new ByteArrayOutputStream();
U.streamXmlToJson(xmlStream, jsonStream, Json.JsonStringBuilder.Step.FOUR_SPACES);
String jsonOutput = jsonStream.toString("UTF-8");
String jsonOutput = jsonStream.toString(StandardCharsets.UTF_8);
assertTrue(jsonOutput.contains(" "), "JSON output should be indented with four spaces.");
}

@Test
void testMapWithEncodingKey(@TempDir Path tempDir) throws IOException {
// Arrange
Path jsonFile = tempDir.resolve("in.json");
Path xmlFile = tempDir.resolve("out.xml");
String encoding = "UTF-16";
// Write json
String jsonText = "{\"#encoding\":\"" + encoding + "\"}";
Files.write(jsonFile, jsonText.getBytes(StandardCharsets.UTF_8));
// Act
U.fileJsonToXml(jsonFile.toString(), xmlFile.toString());
// Assert
byte[] xmlBytes = Files.readAllBytes(xmlFile);
String xmlStr = new String(xmlBytes, encoding);
assertEquals(
"<?xml version=\"1.0\" encoding=\"UTF-16\"?>"
+ System.lineSeparator()
+ "<root></root>",
xmlStr,
"Should write XML with provided encoding when #encoding key present");
}

@Test
void testMapWithoutEncodingKey(@TempDir Path tempDir) throws IOException {
// Arrange
Path jsonFile = tempDir.resolve("in.json");
Path xmlFile = tempDir.resolve("out.xml");
String jsonText = "{}";
Files.write(jsonFile, jsonText.getBytes(StandardCharsets.UTF_8));
// Act
U.fileJsonToXml(
jsonFile.toString(), xmlFile.toString(), Xml.XmlStringBuilder.Step.TWO_SPACES);
// Assert
byte[] xmlBytes = Files.readAllBytes(xmlFile);
String xmlStr = new String(xmlBytes, StandardCharsets.UTF_8);
assertEquals(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ System.lineSeparator()
+ "<root></root>",
xmlStr,
"Should write XML using UTF-8 when #encoding key not present");
}

@Test
void testListResult(@TempDir Path tempDir) throws IOException {
// Arrange
Path jsonFile = tempDir.resolve("in.json");
Path xmlFile = tempDir.resolve("out.xml");
Files.write(jsonFile, "[1,2,3]".getBytes(StandardCharsets.UTF_8));
// Act
U.fileJsonToXml(
jsonFile.toString(), xmlFile.toString(), Xml.XmlStringBuilder.Step.TWO_SPACES);
// Assert
byte[] xmlBytes = Files.readAllBytes(xmlFile);
String xmlStr = new String(xmlBytes, StandardCharsets.UTF_8);
assertEquals(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ System.lineSeparator()
+ "<root>"
+ System.lineSeparator()
+ " <element number=\"true\">1</element>"
+ System.lineSeparator()
+ " <element number=\"true\">2</element>"
+ System.lineSeparator()
+ " <element number=\"true\">3</element>"
+ System.lineSeparator()
+ "</root>",
xmlStr,
"Should write XML using UTF-8 when result is a List");
}
}
Loading