View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau;
18  
19  import static org.apache.juneau.assertions.Verify.*;
20  
21  import java.util.*;
22  
23  import org.apache.juneau.annotation.*;
24  import org.apache.juneau.collections.*;
25  import org.apache.juneau.serializer.*;
26  import org.apache.juneau.swaps.*;
27  
28  /**
29   * Exhaustive serialization tests DynaBean support.
30   */
31  class DynaBean_ComboRoundTripTest extends ComboRoundTripTest_Base {
32  
33  	private static final Calendar SINGLE_DATE = new GregorianCalendar(TimeZone.getTimeZone("PST"));
34  	static {
35  		SINGLE_DATE.setTimeInMillis(0);
36  		SINGLE_DATE.set(1901, 2, 3, 10, 11, 12);
37  	}
38  
39  	private static <T> ComboRoundTrip_Tester.Builder<T> tester(int index, String label, Class<T> type, T bean) {
40  		return ComboRoundTrip_Tester.create(index, label, type, ()->bean).serializerApply(Serializer.Builder::keepNullProperties);
41  	}
42  
43  	private static ComboRoundTrip_Tester<?>[] TESTERS = {
44  		tester(1, "BeanWithDynaField", BeanWithDynaField.class, new BeanWithDynaField().init())
45  			.json("{f1:1,f2a:'a',f2b:'b',f3:3}")
46  			.jsonT("{f1:1,f2a:'a',f2b:'b',f3:3}")
47  			.jsonR("{\n\tf1: 1,\n\tf2a: 'a',\n\tf2b: 'b',\n\tf3: 3\n}")
48  			.xml("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
49  			.xmlT("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
50  			.xmlR("<object>\n\t<f1>1</f1>\n\t<f2a>a</f2a>\n\t<f2b>b</f2b>\n\t<f3>3</f3>\n</object>\n")
51  			.xmlNs("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
52  			.html("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
53  			.htmlT("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
54  			.htmlR("<table>\n\t<tr>\n\t\t<td>f1</td>\n\t\t<td>1</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2a</td>\n\t\t<td>a</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2b</td>\n\t\t<td>b</td>\n\t</tr>\n\t<tr>\n\t\t<td>f3</td>\n\t\t<td>3</td>\n\t</tr>\n</table>\n")
55  			.uon("(f1=1,f2a=a,f2b=b,f3=3)")
56  			.uonT("(f1=1,f2a=a,f2b=b,f3=3)")
57  			.uonR("(\n\tf1=1,\n\tf2a=a,\n\tf2b=b,\n\tf3=3\n)")
58  			.urlEnc("f1=1&f2a=a&f2b=b&f3=3")
59  			.urlEncT("f1=1&f2a=a&f2b=b&f3=3")
60  			.urlEncR("f1=1\n&f2a=a\n&f2b=b\n&f3=3")
61  			.msgPack("84A2663101A3663261A161A3663262A162A2663303")
62  			.msgPackT("84A2663101A3663261A161A3663262A162A2663303")
63  			.rdfXml("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
64  			.rdfXmlT("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
65  			.rdfXmlR("<rdf:RDF>\n  <rdf:Description>\n    <jp:f1>1</jp:f1>\n    <jp:f2a>a</jp:f2a>\n    <jp:f2b>b</jp:f2b>\n    <jp:f3>3</jp:f3>\n  </rdf:Description>\n</rdf:RDF>\n")
66  			.verify(x -> verify(x).isType(BeanWithDynaField.class))
67  			.build(),
68  		tester(2, "BeanWithDynaMethods", BeanWithDynaMethods.class, new BeanWithDynaMethods().init())
69  			.json("{f1:1,f2a:'a',f2b:'b',f3:3}")
70  			.jsonT("{f1:1,f2a:'a',f2b:'b',f3:3}")
71  			.jsonR("{\n\tf1: 1,\n\tf2a: 'a',\n\tf2b: 'b',\n\tf3: 3\n}")
72  			.xml("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
73  			.xmlT("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
74  			.xmlR("<object>\n\t<f1>1</f1>\n\t<f2a>a</f2a>\n\t<f2b>b</f2b>\n\t<f3>3</f3>\n</object>\n")
75  			.xmlNs("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
76  			.html("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
77  			.htmlT("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
78  			.htmlR("<table>\n\t<tr>\n\t\t<td>f1</td>\n\t\t<td>1</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2a</td>\n\t\t<td>a</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2b</td>\n\t\t<td>b</td>\n\t</tr>\n\t<tr>\n\t\t<td>f3</td>\n\t\t<td>3</td>\n\t</tr>\n</table>\n")
79  			.uon("(f1=1,f2a=a,f2b=b,f3=3)")
80  			.uonT("(f1=1,f2a=a,f2b=b,f3=3)")
81  			.uonR("(\n\tf1=1,\n\tf2a=a,\n\tf2b=b,\n\tf3=3\n)")
82  			.urlEnc("f1=1&f2a=a&f2b=b&f3=3")
83  			.urlEncT("f1=1&f2a=a&f2b=b&f3=3")
84  			.urlEncR("f1=1\n&f2a=a\n&f2b=b\n&f3=3")
85  			.msgPack("84A2663101A3663261A161A3663262A162A2663303")
86  			.msgPackT("84A2663101A3663261A161A3663262A162A2663303")
87  			.rdfXml("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
88  			.rdfXmlT("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
89  			.rdfXmlR("<rdf:RDF>\n  <rdf:Description>\n    <jp:f1>1</jp:f1>\n    <jp:f2a>a</jp:f2a>\n    <jp:f2b>b</jp:f2b>\n    <jp:f3>3</jp:f3>\n  </rdf:Description>\n</rdf:RDF>\n")
90  			.verify(x -> verify(x).isType(BeanWithDynaMethods.class))
91  			.verify(x -> x.setterCalled ? null : "Setter not called")
92  			.build(),
93  		tester(3, "BeanWithDynaGetterOnly", BeanWithDynaGetterOnly.class, new BeanWithDynaGetterOnly().init())
94  			.json("{f1:1,f2a:'a',f2b:'b',f3:3}")
95  			.jsonT("{f1:1,f2a:'a',f2b:'b',f3:3}")
96  			.jsonR("{\n\tf1: 1,\n\tf2a: 'a',\n\tf2b: 'b',\n\tf3: 3\n}")
97  			.xml("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
98  			.xmlT("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
99  			.xmlR("<object>\n\t<f1>1</f1>\n\t<f2a>a</f2a>\n\t<f2b>b</f2b>\n\t<f3>3</f3>\n</object>\n")
100 			.xmlNs("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
101 			.html("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
102 			.htmlT("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
103 			.htmlR("<table>\n\t<tr>\n\t\t<td>f1</td>\n\t\t<td>1</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2a</td>\n\t\t<td>a</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2b</td>\n\t\t<td>b</td>\n\t</tr>\n\t<tr>\n\t\t<td>f3</td>\n\t\t<td>3</td>\n\t</tr>\n</table>\n")
104 			.uon("(f1=1,f2a=a,f2b=b,f3=3)")
105 			.uonT("(f1=1,f2a=a,f2b=b,f3=3)")
106 			.uonR("(\n\tf1=1,\n\tf2a=a,\n\tf2b=b,\n\tf3=3\n)")
107 			.urlEnc("f1=1&f2a=a&f2b=b&f3=3")
108 			.urlEncT("f1=1&f2a=a&f2b=b&f3=3")
109 			.urlEncR("f1=1\n&f2a=a\n&f2b=b\n&f3=3")
110 			.msgPack("84A2663101A3663261A161A3663262A162A2663303")
111 			.msgPackT("84A2663101A3663261A161A3663262A162A2663303")
112 			.rdfXml("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
113 			.rdfXmlT("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
114 			.rdfXmlR("<rdf:RDF>\n  <rdf:Description>\n    <jp:f1>1</jp:f1>\n    <jp:f2a>a</jp:f2a>\n    <jp:f2b>b</jp:f2b>\n    <jp:f3>3</jp:f3>\n  </rdf:Description>\n</rdf:RDF>\n")
115 			.verify(x -> verify(x).isType(BeanWithDynaGetterOnly.class))
116 			.build(),
117 		tester(4, "BeanWithDynaFieldSwapped", BeanWithDynaFieldSwapped.class, new BeanWithDynaFieldSwapped().init())
118 			.json("{f1a:'1901-03-03T18:11:12Z'}")
119 			.jsonT("{f1a:'1901-03-03T18:11:12Z'}")
120 			.jsonR("{\n\tf1a: '1901-03-03T18:11:12Z'\n}")
121 			.xml("<object><f1a>1901-03-03T18:11:12Z</f1a></object>")
122 			.xmlT("<object><f1a>1901-03-03T18:11:12Z</f1a></object>")
123 			.xmlR("<object>\n\t<f1a>1901-03-03T18:11:12Z</f1a>\n</object>\n")
124 			.xmlNs("<object><f1a>1901-03-03T18:11:12Z</f1a></object>")
125 			.html("<table><tr><td>f1a</td><td>1901-03-03T18:11:12Z</td></tr></table>")
126 			.htmlT("<table><tr><td>f1a</td><td>1901-03-03T18:11:12Z</td></tr></table>")
127 			.htmlR("<table>\n\t<tr>\n\t\t<td>f1a</td>\n\t\t<td>1901-03-03T18:11:12Z</td>\n\t</tr>\n</table>\n")
128 			.uon("(f1a=1901-03-03T18:11:12Z)")
129 			.uonT("(f1a=1901-03-03T18:11:12Z)")
130 			.uonR("(\n\tf1a=1901-03-03T18:11:12Z\n)")
131 			.urlEnc("f1a=1901-03-03T18:11:12Z")
132 			.urlEncT("f1a=1901-03-03T18:11:12Z")
133 			.urlEncR("f1a=1901-03-03T18:11:12Z")
134 			.msgPack("81A3663161B4313930312D30332D30335431383A31313A31325A")
135 			.msgPackT("81A3663161B4313930312D30332D30335431383A31313A31325A")
136 			.rdfXml("<rdf:RDF>\n<rdf:Description>\n<jp:f1a>1901-03-03T18:11:12Z</jp:f1a>\n</rdf:Description>\n</rdf:RDF>\n")
137 			.rdfXmlT("<rdf:RDF>\n<rdf:Description>\n<jp:f1a>1901-03-03T18:11:12Z</jp:f1a>\n</rdf:Description>\n</rdf:RDF>\n")
138 			.rdfXmlR("<rdf:RDF>\n  <rdf:Description>\n    <jp:f1a>1901-03-03T18:11:12Z</jp:f1a>\n  </rdf:Description>\n</rdf:RDF>\n")
139 			.verify(x -> verify(x).isType(BeanWithDynaFieldSwapped.class))
140 			.verify(x -> verify(x.f1.get("f1a")).isType(Calendar.class))
141 			.build(),
142 		tester(5, "BeanWithDynaFieldStringList", BeanWithDynaFieldStringList.class, new BeanWithDynaFieldStringList().init())
143 			.json("{f1a:['foo','bar']}")
144 			.jsonT("{f1a:['foo','bar']}")
145 			.jsonR("{\n\tf1a: [\n\t\t'foo',\n\t\t'bar'\n\t]\n}")
146 			.xml("<object><f1a><string>foo</string><string>bar</string></f1a></object>")
147 			.xmlT("<object><f1a><string>foo</string><string>bar</string></f1a></object>")
148 			.xmlR("<object>\n\t<f1a>\n\t\t<string>foo</string>\n\t\t<string>bar</string>\n\t</f1a>\n</object>\n")
149 			.xmlNs("<object><f1a><string>foo</string><string>bar</string></f1a></object>")
150 			.html("<table><tr><td>f1a</td><td><ul><li>foo</li><li>bar</li></ul></td></tr></table>")
151 			.htmlT("<table><tr><td>f1a</td><td><ul><li>foo</li><li>bar</li></ul></td></tr></table>")
152 			.htmlR("<table>\n\t<tr>\n\t\t<td>f1a</td>\n\t\t<td>\n\t\t\t<ul>\n\t\t\t\t<li>foo</li>\n\t\t\t\t<li>bar</li>\n\t\t\t</ul>\n\t\t</td>\n\t</tr>\n</table>\n")
153 			.uon("(f1a=@(foo,bar))")
154 			.uonT("(f1a=@(foo,bar))")
155 			.uonR("(\n\tf1a=@(\n\t\tfoo,\n\t\tbar\n\t)\n)")
156 			.urlEnc("f1a=@(foo,bar)")
157 			.urlEncT("f1a=@(foo,bar)")
158 			.urlEncR("f1a=@(\n\tfoo,\n\tbar\n)")
159 			.msgPack("81A366316192A3666F6FA3626172")
160 			.msgPackT("81A366316192A3666F6FA3626172")
161 			.rdfXml("<rdf:RDF>\n<rdf:Description>\n<jp:f1a>\n<rdf:Seq>\n<rdf:li>foo</rdf:li>\n<rdf:li>bar</rdf:li>\n</rdf:Seq>\n</jp:f1a>\n</rdf:Description>\n</rdf:RDF>\n")
162 			.rdfXmlT("<rdf:RDF>\n<rdf:Description>\n<jp:f1a>\n<rdf:Seq>\n<rdf:li>foo</rdf:li>\n<rdf:li>bar</rdf:li>\n</rdf:Seq>\n</jp:f1a>\n</rdf:Description>\n</rdf:RDF>\n")
163 			.rdfXmlR("<rdf:RDF>\n  <rdf:Description>\n    <jp:f1a>\n      <rdf:Seq>\n        <rdf:li>foo</rdf:li>\n        <rdf:li>bar</rdf:li>\n      </rdf:Seq>\n    </jp:f1a>\n  </rdf:Description>\n</rdf:RDF>\n")
164 			.verify(x -> verify(x).isType(BeanWithDynaFieldStringList.class))
165 			.build(),
166 		tester(6, "BeanWithDynaMethodsAndExtraKeys", BeanWithDynaMethodsAndExtraKeys.class, new BeanWithDynaMethodsAndExtraKeys().init())
167 			.json("{f1:1,f2a:'a',f2b:'b',f3:3}")
168 			.jsonT("{f1:1,f2a:'a',f2b:'b',f3:3}")
169 			.jsonR("{\n\tf1: 1,\n\tf2a: 'a',\n\tf2b: 'b',\n\tf3: 3\n}")
170 			.xml("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
171 			.xmlT("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
172 			.xmlR("<object>\n\t<f1>1</f1>\n\t<f2a>a</f2a>\n\t<f2b>b</f2b>\n\t<f3>3</f3>\n</object>\n")
173 			.xmlNs("<object><f1>1</f1><f2a>a</f2a><f2b>b</f2b><f3>3</f3></object>")
174 			.html("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
175 			.htmlT("<table><tr><td>f1</td><td>1</td></tr><tr><td>f2a</td><td>a</td></tr><tr><td>f2b</td><td>b</td></tr><tr><td>f3</td><td>3</td></tr></table>")
176 			.htmlR("<table>\n\t<tr>\n\t\t<td>f1</td>\n\t\t<td>1</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2a</td>\n\t\t<td>a</td>\n\t</tr>\n\t<tr>\n\t\t<td>f2b</td>\n\t\t<td>b</td>\n\t</tr>\n\t<tr>\n\t\t<td>f3</td>\n\t\t<td>3</td>\n\t</tr>\n</table>\n")
177 			.uon("(f1=1,f2a=a,f2b=b,f3=3)")
178 			.uonT("(f1=1,f2a=a,f2b=b,f3=3)")
179 			.uonR("(\n\tf1=1,\n\tf2a=a,\n\tf2b=b,\n\tf3=3\n)")
180 			.urlEnc("f1=1&f2a=a&f2b=b&f3=3")
181 			.urlEncT("f1=1&f2a=a&f2b=b&f3=3")
182 			.urlEncR("f1=1\n&f2a=a\n&f2b=b\n&f3=3")
183 			.msgPack("84A2663101A3663261A161A3663262A162A2663303")
184 			.msgPackT("84A2663101A3663261A161A3663262A162A2663303")
185 			.rdfXml("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
186 			.rdfXmlT("<rdf:RDF>\n<rdf:Description>\n<jp:f1>1</jp:f1>\n<jp:f2a>a</jp:f2a>\n<jp:f2b>b</jp:f2b>\n<jp:f3>3</jp:f3>\n</rdf:Description>\n</rdf:RDF>\n")
187 			.rdfXmlR("<rdf:RDF>\n  <rdf:Description>\n    <jp:f1>1</jp:f1>\n    <jp:f2a>a</jp:f2a>\n    <jp:f2b>b</jp:f2b>\n    <jp:f3>3</jp:f3>\n  </rdf:Description>\n</rdf:RDF>\n")
188 			.verify(x -> verify(x).isType(BeanWithDynaMethodsAndExtraKeys.class))
189 			.verify(x -> x.setterCalled, "Setter not called")
190 			.build()
191 	};
192 
193 	static ComboRoundTrip_Tester<?>[] testers() {
194 		return TESTERS;
195 	}
196 
197 	@Bean(sort=true)
198 	public static class BeanWithDynaField {
199 		public int f1;
200 		@Beanp(name="*")
201 		public Map<String,Object> f2 = new LinkedHashMap<>();
202 		public int f3;
203 
204 		public BeanWithDynaField init() {
205 			this.f1 = 1;
206 			this.f2 = JsonMap.of("f2a", "a", "f2b", "b");
207 			this.f3 = 3;
208 			return this;
209 		}
210 	}
211 
212 	@Bean(sort=true)
213 	public static class BeanWithDynaMethods {
214 
215 		private Map<String,Object> f2 = new LinkedHashMap<>();
216 		private boolean setterCalled;
217 
218 		private int f1;
219 		public int getF1() { return f1; }
220 		public void setF1(int v) { f1 = v; }
221 
222 		private int f3;
223 		public int getF3() { return f3; }
224 		public void setF3(int v) { f3 = v; }
225 
226 		@Beanp(name="*")
227 		public Map<String, Object> xxx() {
228 			return f2;
229 		}
230 
231 		@Beanp(name="*")
232 		public void setYYY(String name, Object o) {
233 			setterCalled = true;
234 			this.f2.put(name, o);
235 		}
236 
237 		public BeanWithDynaMethods init() {
238 			this.f1 = 1;
239 			this.f2 = JsonMap.of("f2a", "a", "f2b", "b");
240 			this.f3 = 3;
241 			return this;
242 		}
243 	}
244 
245 	@Bean(sort=true)
246 	public static class BeanWithDynaMethodsAndExtraKeys {
247 
248 		private Map<String,Object> f2 = new LinkedHashMap<>();
249 		private boolean setterCalled;
250 
251 		private int f1;
252 		public int getF1() { return f1; }
253 		public void setF1(int v) { f1 = v; }
254 
255 		private int f3;
256 		public int getF3() { return f3; }
257 		public void setF3(int v) { f3 = v; }
258 
259 		@Beanp(name="*")
260 		public Object get(String name) {
261 			return f2.get(name);
262 		}
263 
264 		@Beanp(name="*")
265 		public void set(String name, Object o) {
266 			setterCalled = true;
267 			this.f2.put(name, o);
268 		}
269 
270 		@Beanp(name="*")
271 		public Collection<String> getExtraKeys() {
272 			return f2.keySet();
273 		}
274 
275 		public BeanWithDynaMethodsAndExtraKeys init() {
276 			this.f1 = 1;
277 			this.f2 = JsonMap.of("f2a", "a", "f2b", "b");
278 			this.f3 = 3;
279 			return this;
280 		}
281 	}
282 
283 	@Bean(sort=true)
284 	public static class BeanWithDynaGetterOnly {
285 
286 		private Map<String,Object> f2 = new LinkedHashMap<>();
287 
288 		private int f1;
289 		public int getF1() { return f1; }
290 		public void setF1(int v) { f1 = v; }
291 
292 		private int f3;
293 		public int getF3() { return f3; }
294 		public void setF3(int v) { f3 = v; }
295 
296 		@Beanp(name="*")
297 		public Map<String, Object> xxx() {
298 			return f2;
299 		}
300 
301 		public BeanWithDynaGetterOnly init() {
302 			f1 = 1;
303 			f2 = JsonMap.of("f2a", "a", "f2b", "b");
304 			f3 = 3;
305 			return this;
306 		}
307 	}
308 
309 	@Bean(sort=true)
310 	public static class BeanWithDynaFieldSwapped {
311 		@Beanp(name="*")
312 		@Swap(TemporalCalendarSwap.IsoInstant.class)
313 		public Map<String,Calendar> f1 = new LinkedHashMap<>();
314 
315 		public BeanWithDynaFieldSwapped init() {
316 			f1.put("f1a", SINGLE_DATE);
317 			return this;
318 		}
319 	}
320 
321 	@Bean(sort=true)
322 	public static class BeanWithDynaFieldStringList {
323 		@Beanp(name="*")
324 		public Map<String,List<String>> f1 = new LinkedHashMap<>();
325 
326 		public BeanWithDynaFieldStringList init() {
327 			f1.put("f1a", Arrays.asList(new String[]{"foo","bar"}));
328 			return this;
329 		}
330 	}
331 }