Skip to content

Conversation

@Pgarrett
Copy link
Collaborator

@Pgarrett Pgarrett commented Jan 22, 2026

ASCII control characters were being escaped by Jackson when using DTOs. Control characters in a JSON payload generate an invalid payload, which was being tested by EvoMaster. As such, we created a custom object mapper that will not escape the ASCII control characters, allowing for incorrect payloads to be tested.

@Pgarrett Pgarrett changed the title Phg/object mapper v2 Add ObjectMapper unescaping ASCII control characters when using DTOs Jan 22, 2026
@Pgarrett Pgarrett marked this pull request as ready for review January 22, 2026 20:15
@Pgarrett Pgarrett requested a review from arcuri82 January 22, 2026 20:15
import java.nio.file.Path

class JavaDtoOutput: JvmDtoOutput() {
class JavaDtoOutput(val outputFormat: OutputFormat): JvmDtoOutput() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is any special reason to keep outputFormat here as a field? also, in that case, shouldnt we have a init{} block to validate it? (ie throw IllegalArgument if not for Java)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No special reason, but DtoOutput is instantiated depending on the actual OutputFormat:

val dtoOutput = when {
outputFormat.isJava() -> JavaDtoOutput(outputFormat)
outputFormat.isKotlin() -> KotlinDtoOutput(outputFormat)
else -> throw IllegalStateException("$outputFormat output format does not support DTOs as request payloads.")
}

lines.add("public ObjectMapper create(Type cls, String charset) {")
lines.indented {
lines.add("ObjectMapper mapper = new ObjectMapper();")
lines.add("mapper.registerModule(new Jdk8Module());")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs some comment explanations

import java.nio.file.Path

class KotlinDtoOutput: JvmDtoOutput() {
class KotlinDtoOutput(val outputFormat: OutputFormat): JvmDtoOutput() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

input validation?

lines.indented {
lines.add(".jsonConfig(JsonConfig.jsonConfig().numberReturnType(JsonPathConfig.NumberReturnType.DOUBLE))")
lines.add(".redirect(redirectConfig().followRedirects(false))")
if (config.dtoSupportedForPayload() && containsDtos) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need some comments here to explain why this is done

lines.add(".redirect(redirectConfig().followRedirects(false))")
if (config.dtoSupportedForPayload() && containsDtos) {
lines.indented {
lines.add(".objectMapperConfig(")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this now always applied? so we go through this custom mapper even if there are no issues with the payloads?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but it's only being applied for escaping:

lines.add("mapper.factory.setCharacterEscapes(NoEscapeControlChars())")
and for that operation in particular we're just not escaping the ASCII control characters. Also, I wouldn't know how to apply or not the mapper depending on issues or not with the payload, how could we detect that there could be an issue?

@Pgarrett Pgarrett requested a review from arcuri82 January 28, 2026 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants