XML to JSON Converter (java, written by Codex)
envgap__codex__java-t1-3
Written by a coding agent; not on GitHubWritten 2026-03-02
01 / FAILURE SIGNATURE
As the study recorded it
None
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
pom.xml- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
codex/java-t1 #3 · read the task the agent was given
Codex wrote this java project from the task below. It installed and ran on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: XML to JSON Converter Write a program that converts XML documents to JSON format while preserving the document structure including attributes, namespaces, CDATA sections, and mixed content. It should handle complex real-world XML with deeply nested elements. FUNCTIONAL REQUIREMENTS: - Accept an XML file path as a command-line argument - Parse the full XML document including attributes, namespaces, text content, CDATA sections, and comments - Convert to JSON preserving the hierarchy: elements become objects, repeated elements become arrays, attributes are prefixed with @ symbol, text content uses #text key - Handle namespace prefixes by including them in key names - Support converting multiple XML files in a directory via a --batch flag - Print the resulting JSON to console with pretty-print formatting (indented) - Save the output as a .json file with the same base name as the input - If no input file is given, generate a sample XML document with nested elements, attributes, namespaces, CDATA, and mixed content, then convert it - Handle malformed XML with clear error messages indicating the line and column of the problem - Support an optional --compact flag to output minified JSON Create a complete Java project for a clean Ubuntu 22.04 machine with only JDK 17+ installed. Include: - Source code - pom.xml with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
3 files, exactly as written, before any repair.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tmlr.codex_generated.p03</groupId>
<artifactId>xml-to-json-converter</artifactId>
<version>1.0.0</version>
<name>XML to JSON Converter</name>
<description>XML to JSON converter preserving attributes, namespaces, CDATA, comments, and mixed content.</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<mainClass>XmlToJsonConverter</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
README.md
# XML to JSON Converter (Java) Converts XML files to JSON while preserving nested structure, attributes, namespace prefixes, CDATA/text, comments, and mixed content. ## Features - Accepts an XML file path as CLI input. - Parses attributes, namespaces, text, CDATA, comments, and nested elements. - Conversion rules: - attributes => `@attr` - text/CDATA => `#text` - comments => `#comment` - repeated elements => arrays - namespace prefixes preserved in keys - `--batch` converts all `.xml` files in a directory. - Pretty JSON output by default. - `--compact` for minified JSON. - Saves output as `<base>.json` next to input. - If no file is provided, generates `sample.xml` and converts it. - Malformed XML reports line and column. ## Requirements - Ubuntu 22.04 - JDK 17+ ## Dependencies (Pinned) No external dependencies are used. - Direct dependencies: none - Transitive dependencies: none `pom.xml` includes pinned Maven plugin versions. ## Build and Run ### JDK only ```bash cd TMLR/code_generation/codex_generated/p_03/java mkdir -p out javac -d out src/main/java/XmlToJsonConverter.java java -cp out XmlToJsonConverter ./input.xml ``` Batch mode: ```bash java -cp out XmlToJsonConverter --batch ./xml_dir ``` Compact output: ```bash java -cp out XmlToJsonConverter ./input.xml --compact ``` No args (generate sample): ```bash java -cp out XmlToJsonConverter ``` ### Maven ```bash mvn -q compile mvn -q exec:java -Dexec.args="./input.xml" ```
src/main/java/XmlToJsonConverter.java
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
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.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.xml.sax.InputSource;
public class XmlToJsonConverter {
public static void main(String[] args) {
try {
int exitCode = run(args);
System.exit(exitCode);
} catch (Exception ex) {
System.err.println("Unexpected failure: " + ex.getMessage());
System.exit(1);
}
}
private static int run(String[] args) throws IOException {
boolean compact = false;
boolean batch = false;
List<String> paths = new ArrayList<>();
for (String arg : args) {
if ("--compact".equals(arg)) {
compact = true;
} else if ("--batch".equals(arg)) {
batch = true;
} else {
paths.add(arg);
}
}
if (batch) {
if (paths.size() != 1) {
System.err.println("Usage: java -cp out XmlToJsonConverter --batch <directory> [--compact]");
return 1;
}
return convertBatch(paths.get(0), compact);
}
if (paths.isEmpty()) {
Path samplePath = Paths.get("sample.xml").toAbsolutePath().normalize();
Files.writeString(samplePath, sampleXml(), StandardCharsets.UTF_8);
System.out.println("No input file provided. Generated sample XML: " + samplePath);
return convertSingle(samplePath, compact);
}
if (paths.size() != 1) {
System.err.println("Usage: java -cp out XmlToJsonConverter <file.xml> [--compact]");
System.err.println(" or: java -cp out XmlToJsonConverter --batch <directory> [--compact]");
return 1;
}
Path input = Paths.get(paths.get(0)).toAbsolutePath().normalize();
return convertSingle(input, compact);
}
private static int convertBatch(String directory, boolean compact) throws IOException {
Path dir = Paths.get(directory).toAbsolutePath().normalize();
if (!Files.isDirectory(dir)) {
System.err.println("Batch directory error: not a directory: " + dir);
return 1;
}
List<Path> xmlFiles = new ArrayList<>();
try (var stream = Files.list(dir)) {
stream.filter(Files::isRegularFile)
.filter(path -> path.getFileName().toString().toLowerCase().endsWith(".xml"))
.forEach(xmlFiles::add);
}
Collections.sort(xmlFiles);
if (xmlFiles.isEmpty()) {
System.out.println("No XML files found in " + dir);
return 0;
}
for (Path xmlFile : xmlFiles) {
System.out.println("\n== " + xmlFile + " ==");
int code = convertSingle(xmlFile, compact);
if (code != 0) {
return code;
}
}
return 0;
}
private static int convertSingle(Path xmlFile, boolean compact) throws IOException {
final String xmlText;
try {
xmlText = Files.readString(xmlFile, StandardCharsets.UTF_8);
} catch (IOException ex) {
System.err.println("File read error (" + xmlFile + "): " + ex.getMessage());
return 1;
}
Document doc;
try {
doc = parseXml(xmlText);
} catch (SAXParseException ex) {
System.err.println("Malformed XML (" + xmlFile + "): " + ex.getMessage()
+ " (line " + ex.getLineNumber() + ", column " + ex.getColumnNumber() + ")");
return 1;
} catch (SAXException | ParserConfigurationException ex) {
System.err.println("XML parse error (" + xmlFile + "): " + ex.getMessage());
return 1;
}
Element root = doc.getDocumentElement();
Map<String, Object> converted = new LinkedHashMap<>();
converted.put(root.getTagName(), elementToObject(root));
String jsonText = compact ? JsonWriter.toJson(converted) : JsonWriter.toPrettyJson(converted);
System.out.println(jsonText);
Path outPath = xmlFile.resolveSibling(removeExtension(xmlFile.getFileName().toString()) + ".json");
Files.writeString(outPath, jsonText + System.lineSeparator(), StandardCharsets.UTF_8);
System.out.println("Saved: " + outPath.toAbsolutePath().normalize());
return 0;
}
private static Document parseXml(String xmlText) throws ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setIgnoringComments(false);
factory.setCoalescing(false);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource source = new InputSource(new StringReader(xmlText));
return builder.parse(source);
}
private static Map<String, Object> elementToObject(Element element) {
Map<String, Object> result = new LinkedHashMap<>();
NamedNodeMap attrs = element.getAttributes();
for (int i = 0; i < attrs.getLength(); i++) {
Node attr = attrs.item(i);
result.put("@" + attr.getNodeName(), attr.getNodeValue());
}
Map<String, List<Object>> groupedChildren = new LinkedHashMap<>();
List<String> textParts = new ArrayList<>();
List<String> comments = new ArrayList<>();
NodeList children = element.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
short type = child.getNodeType();
if (type == Node.ELEMENT_NODE) {
Element childElement = (Element) child;
groupedChildren.computeIfAbsent(childElement.getTagName(), k -> new ArrayList<>())
.add(elementToObject(childElement));
} else if (type == Node.TEXT_NODE || type == Node.CDATA_SECTION_NODE) {
String text = child.getNodeValue();
if (text != null && !text.trim().isEmpty()) {
textParts.add(text);
}
} else if (type == Node.COMMENT_NODE) {
String value = ((Comment) child).getData();
comments.add(value);
}
}
for (Map.Entry<String, List<Object>> entry : groupedChildren.entrySet()) {
if (entry.getValue().size() == 1) {
result.put(entry.getKey(), entry.getValue().get(0));
} else {
result.put(entry.getKey(), entry.getValue());
}
}
if (!textParts.isEmpty()) {
result.put("#text", String.join(" ", textParts));
}
if (!comments.isEmpty()) {
result.put("#comment", comments.size() == 1 ? comments.get(0) : comments);
}
return result;
}
private static String removeExtension(String fileName) {
int idx = fileName.lastIndexOf('.');
return idx <= 0 ? fileName : fileName.substring(0, idx);
}
private static String sampleXml() {
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<catalog xmlns:bk=\"http://example.com/book\" xmlns:meta=\"http://example.com/meta\" meta:version=\"1.2\">\n"
+ " <!-- Inventory catalog -->\n"
+ " <bk:book id=\"b1\" lang=\"en\">\n"
+ " <bk:title>XML & JSON Guide</bk:title>\n"
+ " <bk:author>Jane Doe</bk:author>\n"
+ " <bk:description><![CDATA[Great book with <examples> and mixed content]]></bk:description>\n"
+ " <meta:note priority=\"high\">Read <meta:emphasis>carefully</meta:emphasis> now.</meta:note>\n"
+ " </bk:book>\n"
+ " <bk:book id=\"b2\" lang=\"fr\">\n"
+ " <bk:title>Guide Avancé</bk:title>\n"
+ " <bk:author>Jean Dupont</bk:author>\n"
+ " </bk:book>\n"
+ "</catalog>\n";
}
private static final class JsonWriter {
static String toJson(Object value) {
StringBuilder sb = new StringBuilder();
write(value, sb, false, 0);
return sb.toString();
}
static String toPrettyJson(Object value) {
StringBuilder sb = new StringBuilder();
write(value, sb, true, 0);
return sb.toString();
}
@SuppressWarnings("unchecked")
private static void write(Object value, StringBuilder sb, boolean pretty, int indent) {
if (value == null) {
sb.append("null");
return;
}
if (value instanceof String) {
sb.append('"').append(escape((String) value)).append('"');
return;
}
if (value instanceof Boolean || value instanceof Integer || value instanceof Long) {
sb.append(value);
return;
}
if (value instanceof Number) {
double d = ((Number) value).doubleValue();
if (Math.rint(d) == d) {
sb.append((long) d);
} else {
sb.append(d);
}
return;
}
if (value instanceof List<?>) {
List<Object> list = (List<Object>) value;
sb.append('[');
if (!list.isEmpty()) {
if (pretty) sb.append('\n');
for (int i = 0; i < list.size(); i++) {
if (pretty) indent(sb, indent + 1);
write(list.get(i), sb, pretty, indent + 1);
if (i < list.size() - 1) sb.append(',');
if (pretty) sb.append('\n');
}
if (pretty) indent(sb, indent);
}
sb.append(']');
return;
}
if (value instanceof Map<?, ?>) {
Map<String, Object> map = (Map<String, Object>) value;
sb.append('{');
if (!map.isEmpty()) {
if (pretty) sb.append('\n');
int i = 0;
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (pretty) indent(sb, indent + 1);
sb.append('"').append(escape(entry.getKey())).append('"');
sb.append(pretty ? ": " : ":");
write(entry.getValue(), sb, pretty, indent + 1);
if (i < map.size() - 1) sb.append(',');
if (pretty) sb.append('\n');
i++;
}
if (pretty) indent(sb, indent);
}
sb.append('}');
return;
}
sb.append('"').append(escape(String.valueOf(value))).append('"');
}
private static void indent(StringBuilder sb, int level) {
for (int i = 0; i < level; i++) sb.append(" ");
}
private static String escape(String text) {
StringBuilder out = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char ch = text.charAt(i);
switch (ch) {
case '"':
out.append("\\\"");
break;
case '\\':
out.append("\\\\");
break;
case '\b':
out.append("\\b");
break;
case '\f':
out.append("\\f");
break;
case '\n':
out.append("\\n");
break;
case '\r':
out.append("\\r");
break;
case '\t':
out.append("\\t");
break;
default:
if (ch < 0x20) {
out.append(String.format("\\u%04x", (int) ch));
} else {
out.append(ch);
}
}
}
return out.toString();
}
}
}