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