package com.fasterxml.jackson.databind.struct;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
/**
* Unit tests for "POJO as array" feature using Builder-style
* POJO construction.
*/
public class TestPOJOAsArrayWithBuilder extends BaseMapTest
{
@JsonDeserialize(builder=SimpleBuilderXY.class)
@JsonFormat(shape=JsonFormat.Shape.ARRAY)
@JsonPropertyOrder(alphabetic=true)
static class ValueClassXY
{
final int _x, _y;
protected ValueClassXY(int x, int y) {
_x = x+1;
_y = y+1;
}
}
@JsonFormat(shape=JsonFormat.Shape.ARRAY)
static class SimpleBuilderXY
{
public int x, y;
protected SimpleBuilderXY() { }
protected SimpleBuilderXY(int x0, int y0) {
x = x0;
y = y0;
}
public SimpleBuilderXY withX(int x0) {
this.x = x0;
return this;
}
public SimpleBuilderXY withY(int y0) {
this.y = y0;
return this;
}
public ValueClassXY build() {
return new ValueClassXY(x, y);
}
}
// Also, with creator:
@JsonDeserialize(builder=CreatorBuilder.class)
@JsonFormat(shape=JsonFormat.Shape.ARRAY)
@JsonPropertyOrder(alphabetic=true)
static class CreatorValue
{
final int a, b, c;
protected CreatorValue(int a, int b, int c) {
this.a = a;
this.b = b;
this.c = c;
}
}
@JsonFormat(shape=JsonFormat.Shape.ARRAY)
static class CreatorBuilder {
private final int a, b;
private int c;
@JsonCreator
public CreatorBuilder(@JsonProperty("a") int a,
@JsonProperty("b") int b)
{
this.a = a;
this.b = b;
}
@JsonView(String.class)
public CreatorBuilder withC(int v) {
c = v;
return this;
}
public CreatorValue build() {
return new CreatorValue(a, b, c);
}
}
/*
/*****************************************************
/* Basic tests
/*****************************************************
*/
private final static ObjectMapper MAPPER = new ObjectMapper();
public void testSimpleBuilder() throws Exception
{
// Ok, first, ensure that serializer will "black out" filtered properties
ValueClassXY value = MAPPER.readValue("[1,2]", ValueClassXY.class);
assertEquals(2, value._x);
assertEquals(3, value._y);
}
// Won't work, but verify exception
public void testBuilderWithUpdate() throws Exception
{
// Ok, first, simple case of all values being present
try {
/*value =*/ MAPPER.readerFor(ValueClassXY.class)
.withValueToUpdate(new ValueClassXY(6, 7))
.readValue("[1,2]");
fail("Should not pass");
} catch (InvalidDefinitionException e) {
verifyException(e, "Deserialization of");
verifyException(e, "by passing existing instance");
verifyException(e, "ValueClassXY");
}
}
/*
/*****************************************************
/* Creator test(s)
/*****************************************************
*/
// test to ensure @JsonCreator also works
public void testWithCreator() throws Exception
{
CreatorValue value = MAPPER.readValue("[1,2,3]", CreatorValue.class);
assertEquals(1, value.a);
assertEquals(2, value.b);
assertEquals(3, value.c);
// and should be ok with partial too?
value = MAPPER.readValue("[1,2]", CreatorValue.class);
assertEquals(1, value.a);
assertEquals(2, value.b);
assertEquals(0, value.c);
value = MAPPER.readValue("[1]", CreatorValue.class);
assertEquals(1, value.a);
assertEquals(0, value.b);
assertEquals(0, value.c);
value = MAPPER.readValue("[]", CreatorValue.class);
assertEquals(0, value.a);
assertEquals(0, value.b);
assertEquals(0, value.c);
}
public void testWithCreatorAndView() throws Exception
{
ObjectReader reader = MAPPER.readerFor(CreatorValue.class);
CreatorValue value;
// First including values in view
value = reader.withView(String.class).readValue("[1,2,3]");
assertEquals(1, value.a);
assertEquals(2, value.b);
assertEquals(3, value.c);
// then not including view
value = reader.withView(Character.class).readValue("[1,2,3]");
assertEquals(1, value.a);
assertEquals(2, value.b);
assertEquals(0, value.c);
}
/*
/*****************************************************
/* Failure tests
/*****************************************************
*/
public void testUnknownExtraProp() throws Exception
{
String json = "[1, 2, 3, 4]";
try {
MAPPER.readValue(json, ValueClassXY.class);
fail("should not pass with extra element");
} catch (MismatchedInputException e) {
verifyException(e, "Unexpected JSON values");
}
// but actually fine if skip-unknown set
ValueClassXY v = MAPPER.readerFor(ValueClassXY.class)
.without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.readValue(json);
assertNotNull(v);
// note: +1 for both so
assertEquals(v._x, 2);
assertEquals(v._y, 3);
}
}