diff --git a/src/main/java/com/github/underscore/U.java b/src/main/java/com/github/underscore/U.java index a1873a4d..1c0a5c63 100644 --- a/src/main/java/com/github/underscore/U.java +++ b/src/main/java/com/github/underscore/U.java @@ -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; @@ -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); @@ -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; diff --git a/src/test/java/com/github/underscore/UnderscoreTest.java b/src/test/java/com/github/underscore/UnderscoreTest.java index 50aa9781..21605d8b 100644 --- a/src/test/java/com/github/underscore/UnderscoreTest.java +++ b/src/test/java/com/github/underscore/UnderscoreTest.java @@ -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 '{'."); @@ -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."); @@ -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."); @@ -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( + "" + + System.lineSeparator() + + "", + 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( + "" + + System.lineSeparator() + + "", + 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( + "" + + System.lineSeparator() + + "" + + System.lineSeparator() + + " 1" + + System.lineSeparator() + + " 2" + + System.lineSeparator() + + " 3" + + System.lineSeparator() + + "", + xmlStr, + "Should write XML using UTF-8 when result is a List"); + } }