• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.struct;
2 
3 import com.fasterxml.jackson.annotation.*;
4 
5 import com.fasterxml.jackson.databind.BaseMapTest;
6 import com.fasterxml.jackson.databind.DeserializationFeature;
7 import com.fasterxml.jackson.databind.ObjectMapper;
8 import com.fasterxml.jackson.databind.ObjectReader;
9 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
10 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
11 import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
12 
13 /**
14  * Unit tests for "POJO as array" feature using Builder-style
15  * POJO construction.
16  */
17 public class TestPOJOAsArrayWithBuilder extends BaseMapTest
18 {
19     @JsonDeserialize(builder=SimpleBuilderXY.class)
20     @JsonFormat(shape=JsonFormat.Shape.ARRAY)
21     @JsonPropertyOrder(alphabetic=true)
22     static class ValueClassXY
23     {
24         final int _x, _y;
25 
ValueClassXY(int x, int y)26         protected ValueClassXY(int x, int y) {
27             _x = x+1;
28             _y = y+1;
29         }
30     }
31 
32     @JsonFormat(shape=JsonFormat.Shape.ARRAY)
33     static class SimpleBuilderXY
34     {
35         public int x, y;
36 
SimpleBuilderXY()37         protected SimpleBuilderXY() { }
SimpleBuilderXY(int x0, int y0)38         protected SimpleBuilderXY(int x0, int y0) {
39             x = x0;
40             y = y0;
41         }
42 
withX(int x0)43         public SimpleBuilderXY withX(int x0) {
44             this.x = x0;
45             return this;
46         }
47 
withY(int y0)48         public SimpleBuilderXY withY(int y0) {
49             this.y = y0;
50             return this;
51         }
52 
build()53         public ValueClassXY build() {
54             return new ValueClassXY(x, y);
55         }
56     }
57 
58     // Also, with creator:
59 
60     @JsonDeserialize(builder=CreatorBuilder.class)
61     @JsonFormat(shape=JsonFormat.Shape.ARRAY)
62     @JsonPropertyOrder(alphabetic=true)
63     static class CreatorValue
64     {
65         final int a, b, c;
66 
CreatorValue(int a, int b, int c)67         protected CreatorValue(int a, int b, int c) {
68             this.a = a;
69             this.b = b;
70             this.c = c;
71         }
72     }
73 
74     @JsonFormat(shape=JsonFormat.Shape.ARRAY)
75     static class CreatorBuilder {
76         private final int a, b;
77 
78         private int c;
79 
80         @JsonCreator
CreatorBuilder(@sonProperty"a") int a, @JsonProperty("b") int b)81         public CreatorBuilder(@JsonProperty("a") int a,
82                 @JsonProperty("b") int b)
83         {
84             this.a = a;
85             this.b = b;
86         }
87 
88         @JsonView(String.class)
withC(int v)89         public CreatorBuilder withC(int v) {
90             c = v;
91             return this;
92         }
93 
build()94         public CreatorValue build() {
95             return new CreatorValue(a, b, c);
96         }
97     }
98 
99     /*
100     /*****************************************************
101     /* Basic tests
102     /*****************************************************
103      */
104 
105     private final static ObjectMapper MAPPER = new ObjectMapper();
106 
testSimpleBuilder()107     public void testSimpleBuilder() throws Exception
108     {
109         // Ok, first, ensure that serializer will "black out" filtered properties
110         ValueClassXY value = MAPPER.readValue("[1,2]", ValueClassXY.class);
111         assertEquals(2, value._x);
112         assertEquals(3, value._y);
113     }
114 
115     // Won't work, but verify exception
testBuilderWithUpdate()116     public void testBuilderWithUpdate() throws Exception
117     {
118         // Ok, first, simple case of all values being present
119         try {
120             /*value =*/ MAPPER.readerFor(ValueClassXY.class)
121                     .withValueToUpdate(new ValueClassXY(6, 7))
122                     .readValue("[1,2]");
123             fail("Should not pass");
124         } catch (InvalidDefinitionException e) {
125             verifyException(e, "Deserialization of");
126             verifyException(e, "by passing existing instance");
127             verifyException(e, "ValueClassXY");
128         }
129     }
130 
131     /*
132     /*****************************************************
133     /* Creator test(s)
134     /*****************************************************
135      */
136 
137     // test to ensure @JsonCreator also works
testWithCreator()138     public void testWithCreator() throws Exception
139     {
140         CreatorValue value = MAPPER.readValue("[1,2,3]", CreatorValue.class);
141         assertEquals(1, value.a);
142         assertEquals(2, value.b);
143         assertEquals(3, value.c);
144 
145         // and should be ok with partial too?
146         value = MAPPER.readValue("[1,2]", CreatorValue.class);
147         assertEquals(1, value.a);
148         assertEquals(2, value.b);
149         assertEquals(0, value.c);
150 
151         value = MAPPER.readValue("[1]", CreatorValue.class);
152         assertEquals(1, value.a);
153         assertEquals(0, value.b);
154         assertEquals(0, value.c);
155 
156         value = MAPPER.readValue("[]", CreatorValue.class);
157         assertEquals(0, value.a);
158         assertEquals(0, value.b);
159         assertEquals(0, value.c);
160     }
161 
testWithCreatorAndView()162     public void testWithCreatorAndView() throws Exception
163     {
164         ObjectReader reader = MAPPER.readerFor(CreatorValue.class);
165         CreatorValue value;
166 
167         // First including values in view
168         value = reader.withView(String.class).readValue("[1,2,3]");
169         assertEquals(1, value.a);
170         assertEquals(2, value.b);
171         assertEquals(3, value.c);
172 
173         // then not including view
174         value = reader.withView(Character.class).readValue("[1,2,3]");
175         assertEquals(1, value.a);
176         assertEquals(2, value.b);
177         assertEquals(0, value.c);
178     }
179 
180     /*
181     /*****************************************************
182     /* Failure tests
183     /*****************************************************
184      */
185 
testUnknownExtraProp()186     public void testUnknownExtraProp() throws Exception
187     {
188         String json = "[1, 2, 3, 4]";
189         try {
190             MAPPER.readValue(json, ValueClassXY.class);
191             fail("should not pass with extra element");
192         } catch (MismatchedInputException e) {
193             verifyException(e, "Unexpected JSON values");
194         }
195 
196         // but actually fine if skip-unknown set
197         ValueClassXY v = MAPPER.readerFor(ValueClassXY.class)
198                 .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
199                 .readValue(json);
200         assertNotNull(v);
201         // note: +1 for both so
202         assertEquals(v._x, 2);
203         assertEquals(v._y, 3);
204     }
205 }
206