Avoid byte[] to String to byte[] conversion when pretty printing
Previously, PrettyPrintingContentModifier would convert the byte[] content into a String and then back into a byte[]. It did so without consideration for the content’s character set. As a result, it could fail to preserve the correct character encoding. This commit updates PrettyPrintingContentModifier to avoid converting the content into a String and back into a byte[] and to work entirely with byte arrays instead. Removing the intermediate String from the process removes the possibility of the content becoming corrupted. Closes gh-202
This commit is contained in:
@@ -17,8 +17,8 @@
|
||||
package org.springframework.restdocs.operation.preprocess;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -60,7 +60,7 @@ public class PrettyPrintingContentModifier implements ContentModifier {
|
||||
if (originalContent.length > 0) {
|
||||
for (PrettyPrinter prettyPrinter : PRETTY_PRINTERS) {
|
||||
try {
|
||||
return prettyPrinter.prettyPrint(originalContent).getBytes();
|
||||
return prettyPrinter.prettyPrint(originalContent);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
// Continue
|
||||
@@ -72,24 +72,25 @@ public class PrettyPrintingContentModifier implements ContentModifier {
|
||||
|
||||
private interface PrettyPrinter {
|
||||
|
||||
String prettyPrint(byte[] content) throws Exception;
|
||||
byte[] prettyPrint(byte[] content) throws Exception;
|
||||
|
||||
}
|
||||
|
||||
private static final class XmlPrettyPrinter implements PrettyPrinter {
|
||||
|
||||
@Override
|
||||
public String prettyPrint(byte[] original) throws Exception {
|
||||
public byte[] prettyPrint(byte[] original) throws Exception {
|
||||
Transformer transformer = TransformerFactory.newInstance().newTransformer();
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
|
||||
"4");
|
||||
transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "yes");
|
||||
StringWriter transformed = new StringWriter();
|
||||
ByteArrayOutputStream transformed = new ByteArrayOutputStream();
|
||||
transformer.setErrorListener(new SilentErrorListener());
|
||||
transformer.transform(createSaxSource(original),
|
||||
new StreamResult(transformed));
|
||||
return transformed.toString();
|
||||
|
||||
return transformed.toByteArray();
|
||||
}
|
||||
|
||||
private SAXSource createSaxSource(byte[] original)
|
||||
@@ -145,11 +146,13 @@ public class PrettyPrintingContentModifier implements ContentModifier {
|
||||
|
||||
private static final class JsonPrettyPrinter implements PrettyPrinter {
|
||||
|
||||
private final ObjectMapper objectMapper = new ObjectMapper()
|
||||
.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
|
||||
@Override
|
||||
public String prettyPrint(byte[] original) throws IOException {
|
||||
ObjectMapper objectMapper = new ObjectMapper()
|
||||
.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
return objectMapper.writeValueAsString(objectMapper.readTree(original));
|
||||
public byte[] prettyPrint(byte[] original) throws IOException {
|
||||
return this.objectMapper
|
||||
.writeValueAsBytes(this.objectMapper.readTree(original));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2015 the original author or authors.
|
||||
* Copyright 2014-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,17 @@
|
||||
|
||||
package org.springframework.restdocs.operation.preprocess;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.restdocs.test.OutputCapture;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.Matchers.isEmptyString;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
@@ -68,4 +73,16 @@ public class PrettyPrintingContentModifierTests {
|
||||
null), equalTo(content.getBytes()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encodingIsPreserved() throws Exception {
|
||||
Map<String, String> input = new HashMap<>();
|
||||
input.put("japanese", "\u30b3\u30f3\u30c6\u30f3\u30c4");
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> output = objectMapper
|
||||
.readValue(new PrettyPrintingContentModifier().modifyContent(
|
||||
objectMapper.writeValueAsBytes(input), null), Map.class);
|
||||
assertThat(output, is(equalTo(input)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user