수작업으로 만든 Printer
String print(){
Map<String, String> fields = new LinkedHashMap();
fields.put("Display", machine.display());
fields.put("Balance", machine.balance().toString());
fields.put("Coins", formatCoins(machine.coins()));
StringBuilder lines = new StringBuilder("Vending Machine\n");
fields.forEach(
(key, value) -> lines.append(formatLineWithWhitespace(key, value))
);
return lines.toString();
}
private String formatCoins(Integer[] coins) {
// join coins with commas, start with [, end with ]
String joined = Arrays.stream(coins)
.map(Object::toString)
.reduce((a, b) -> a + ", " + b)
.orElse("");
return String.format("[%s]", joined);
}
/** Convenience function that lays out a name and a value at either ends of a fixed-width line.
* eg if you call it with name="Foo" value="Bar" it will return
* Foo Bar
*/
private String formatLineWithWhitespace(String name, String value){
int whitespaceSize = columns - name.length() - value.lengt↓h();
return String.format("%s%s%s\n", name, " ".repeat(Math.max(0, whitespaceSize)), value);
}
ObjectMapper를 이용한 PrettyPrinter
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PrettyJsonWriter {
private ObjectMapper mapper;
public PrettyJsonWriter() {
this.mapper = createMapper();
}
private ObjectMapper createMapper() {
final ObjectMapper mapper = new ObjectMapper();
final JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
mapper.registerModule(javaTimeModule);
return mapper;
}
private String filterOut(final String statements, final String... fields) {
final List<String> fieldList = Arrays.asList(fields);
return Arrays.stream(statements.split("\n"))
.filter(line -> fieldList.stream().noneMatch(line::contains))
.collect(Collectors.joining("\n"));
}
public String prettyPrint(Object obj) {
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
public String prettyPrintWithFilters(Object obj, String... filters) {
String prettyStatements = prettyPrint(obj);
return filterOut(prettyStatements, filters);
}
}
class NewInventoryTransferServiceTest {
private PrettyJsonWriter prettyJsonWriter;
@BeforeEach
void setUp() {
this.prettyJsonWriter = new PrettyJsonWriter();
}
@Test
void create() {
// ...
InventoryTransfer result = create(request);
String prettyStatements = prettyJsonWriter.prettyPrintWithFilters(result,
"createdAt", "createdUserId", "deletedAt", "id", "inventoryTransferId", "serialNumber", "updatedAt", "updatedUserId");
Approvals.verify(prettyStatements);
}
{
"fromWarehouseId": 1,
"toWarehouseId": 2,
"requestedDate": "2024-01-18",
"note": "note",
"status": "ACCEPTED",
"items": [
{
"goodsId": 1,
"requestedQuantity": 10,
"status": "OPEN"
},
{
"goodsId": 2,
"requestedQuantity": 20,
"status": "OPEN"
}
]
}