Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add failing test for #4047 #4049

Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,9 @@ static class TestCommandChild extends TestCommandParent { }
/**********************************************************
*/

final ObjectMapper WRAP_ROOT_MAPPER = new ObjectMapper();
{
WRAP_ROOT_MAPPER.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
}
private final ObjectMapper WRAP_ROOT_MAPPER = jsonMapperBuilder()
.configure(SerializationFeature.WRAP_ROOT_VALUE, true)
.build();

@SuppressWarnings("unchecked")
public void testSuperClass() throws Exception
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.fasterxml.jackson.failing;

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

// [databind#4047] : ObjectMapper.valueToTree will ignore the configuration SerializationFeature.WRAP_ROOT_VALUE
public class TestRootType4047Test extends BaseMapTest {

@JsonRootName("event")
static class Event {
public Long id;
public String name;
}

/*
/**********************************************************
/* Main tests
/**********************************************************
*/

private final String WRAPPED_EVENT_JSON = "{\"event\":{\"id\":1,\"name\":\"foo\"}}";
private final String UNWRAPPED_EVENT_JSON = "{\"id\":1,\"name\":\"foo\"}";

public void testValueToTree() throws Exception {
// Arrange
final ObjectMapper WRAP_ROOT_MAPPER = jsonMapperBuilder()
.enable(SerializationFeature.WRAP_ROOT_VALUE)
.build();
Event value = new Event();
value.id = 1L;
value.name = "foo";

// (1) works
assertEquals(WRAPPED_EVENT_JSON,
WRAP_ROOT_MAPPER.writeValueAsString(value));

// (2) fails w/ {"id":1,"name":"foo"}
assertEquals(WRAPPED_EVENT_JSON,
WRAP_ROOT_MAPPER.valueToTree(value).toString());
}

public void testTreeToValue() throws Exception {
// Arrange
final ObjectMapper UNWRAP_MAPPER = jsonMapperBuilder()
.enable(DeserializationFeature.UNWRAP_ROOT_VALUE)
.build();

/*
* (1) both fails with
* com.fasterxml.jackson.databind.exc.MismatchedInputException: Root name ('event') does not match expected ('JsonNode') for type `com.fasterxml.jackson.databind.JsonNode`
* at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 2] (through reference chain: com.fasterxml.jackson.databind.JsonNode["event"])
*/
UNWRAP_MAPPER.readTree(WRAPPED_EVENT_JSON);
UNWRAP_MAPPER.readTree(UNWRAPPED_EVENT_JSON);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

/cc

Copy link
Member Author

@JooHyukKim JooHyukKim Jul 22, 2023

Choose a reason for hiding this comment

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

When DeserializationFeature.UNWRAP_ROOT_VALUE is enabled, readTree() works like

    UNWRAP_MAPPER.readValue(WRAPPED_EVENT_JSON, JsonNode.class);

But, should it?

Copy link
Member

@cowtowncoder cowtowncoder Jul 25, 2023

Choose a reason for hiding this comment

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

This is tricky: my thinking all along has been that no, WRAP/UNWRAP related to POJOs and should not affect JsonNode: JsonNode (tree model in general) being used to represent JSON exactly as is, with no (or minimal) translations: no naming conventions, no ignorals... and hence no wrapping/unwrapping.

But then again some users disagree, and maybe more importantly, implementation may be such that wrapping/unwrapping occurs outside control of (de)serializer being used.

I suspect this could actually be one reason for handling of:

mapper.readTree(source);
mapper.readValue(source, JsonNode.class);

to possibly differ.

}