ConvertFromTokenBufferTest.java
package tools.jackson.databind.convert;
import java.util.*;
import org.junit.jupiter.api.Test;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.*;
import tools.jackson.databind.testutil.DatabindTestUtil;
import tools.jackson.databind.util.TokenBuffer;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests for {@link ObjectMapper#convertValue(Object, Class)} optimization
* when the source value is already a {@link TokenBuffer}.
* See [databind#5368]
*/
public class ConvertFromTokenBufferTest extends DatabindTestUtil
{
private final ObjectMapper MAPPER = newJsonMapper();
static class SimpleBean {
public int x;
public String name;
public SimpleBean() { }
protected SimpleBean(int x, String name) {
this.x = x;
this.name = name;
}
}
// [databind#5368]: Should reuse TokenBuffer directly without re-serializing
@Test
public void testConvertTokenBufferToBean() throws Exception
{
TokenBuffer buf = _beanToBuffer(42, "test");
SimpleBean result = MAPPER.convertValue(buf, SimpleBean.class);
assertEquals(42, result.x);
assertEquals("test", result.name);
}
// [databind#5368]: Test with JavaType
@Test
public void testConvertTokenBufferToJavaType() throws Exception
{
TokenBuffer buf = _beanToBuffer(123, "javatype");
JavaType type = MAPPER.getTypeFactory().constructType(SimpleBean.class);
SimpleBean result = MAPPER.convertValue(buf, type);
assertEquals(123, result.x);
assertEquals("javatype", result.name);
}
// [databind#5368]: Test with TypeReference
@Test
public void testConvertTokenBufferToTypeReference() throws Exception
{
TokenBuffer buf = _beanToBuffer(456, "foobar");
SimpleBean result = MAPPER.convertValue(buf,
new TypeReference<SimpleBean>() {});
assertEquals(456, result.x);
assertEquals("foobar", result.name);
}
private TokenBuffer _beanToBuffer(int x, String name) throws Exception {
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeStartObject();
buf.writeNumberProperty("x", x);
buf.writeStringProperty("name", name);
buf.writeEndObject();
buf.close();
return buf;
}
// [databind#5368]: Test with Map
@Test
public void testConvertTokenBufferToMap() throws Exception
{
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeStartObject();
buf.writeStringProperty("key1", "value1");
buf.writeNumberProperty("key2", 42);
buf.writeEndObject();
buf.close();
@SuppressWarnings("unchecked")
Map<String, Object> result = MAPPER.convertValue(buf, Map.class);
assertNotNull(result);
assertEquals("value1", result.get("key1"));
assertEquals(42, result.get("key2"));
}
// [databind#5368]: Test with null TokenBuffer value
@Test
public void testConvertNullTokenBuffer() throws Exception
{
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeNull();
buf.close();
SimpleBean result = MAPPER.convertValue(buf, SimpleBean.class);
assertNull(result);
}
// [databind#5368]: Test with array in TokenBuffer
@Test
public void testConvertTokenBufferArray() throws Exception
{
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeStartArray();
buf.writeStartObject();
buf.writeNumberProperty("x", 1);
buf.writeStringProperty("name", "first");
buf.writeEndObject();
buf.writeStartObject();
buf.writeNumberProperty("x", 2);
buf.writeStringProperty("name", "second");
buf.writeEndObject();
buf.writeEndArray();
buf.close();
SimpleBean[] result = MAPPER.convertValue(buf, SimpleBean[].class);
assertNotNull(result);
assertEquals(2, result.length);
assertEquals(1, result[0].x);
assertEquals("first", result[0].name);
assertEquals(2, result[1].x);
assertEquals("second", result[1].name);
}
// [databind#5368]: Verify TokenBuffer can still be used after conversion
// (asParser() creates new stateful instance)
@Test
public void testTokenBufferReusableAfterConvert() throws Exception
{
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeStartObject();
buf.writeNumberProperty("x", 99);
buf.writeStringProperty("name", "reusable");
buf.writeEndObject();
buf.close();
// First conversion
SimpleBean result1 = MAPPER.convertValue(buf, SimpleBean.class);
assertNotNull(result1);
assertEquals(99, result1.x);
// Second conversion - should work because asParser() creates new state
SimpleBean result2 = MAPPER.convertValue(buf, SimpleBean.class);
assertNotNull(result2);
assertEquals(99, result2.x);
assertEquals("reusable", result2.name);
}
// [databind#5368]: Test with USE_BIG_DECIMAL_FOR_FLOATS feature
@Test
public void testConvertTokenBufferWithBigDecimalFeature() throws Exception
{
ObjectMapper mapper = jsonMapperBuilder()
.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
.build();
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeStartObject();
buf.writeStringProperty("value", "test");
buf.writeEndObject();
buf.close();
@SuppressWarnings("unchecked")
Map<String, Object> result = mapper.convertValue(buf, Map.class);
assertNotNull(result);
assertEquals("test", result.get("value"));
}
// [databind#5368]: Ensure regular (non-TokenBuffer) conversion still works
@Test
public void testConvertFromRegularObjectStillWorks() throws Exception
{
Map<String, Object> map = new LinkedHashMap<>();
map.put("x", 77);
map.put("name", "regular");
SimpleBean result = MAPPER.convertValue(map, SimpleBean.class);
assertNotNull(result);
assertEquals(77, result.x);
assertEquals("regular", result.name);
}
// [databind#5368]: Test with empty TokenBuffer
@Test
public void testConvertEmptyTokenBuffer() throws Exception
{
TokenBuffer buf = TokenBuffer.forGeneration();
buf.writeStartObject();
buf.writeEndObject();
buf.close();
SimpleBean result = MAPPER.convertValue(buf, SimpleBean.class);
assertNotNull(result);
assertEquals(0, result.x);
assertNull(result.name);
}
}