• R/O
  • SSH
  • HTTPS

jsonic: コミット


コミットメタ情報

リビジョン1853 (tree)
日時2015-05-23 14:04:10
作者hizuno

ログメッセージ

(メッセージはありません)

変更サマリ

差分

--- trunk/jsonic-1.3/pom.xml.asc (revision 1852)
+++ trunk/jsonic-1.3/pom.xml.asc (revision 1853)
@@ -1,11 +1,11 @@
11 -----BEGIN PGP SIGNATURE-----
22 Version: GnuPG v1.4.11 (MingW32)
33
4-iQEcBAABAgAGBQJUTNHcAAoJEHqIsNfmElEVszcH/iutn5o0enRW4spvvG/rQ/Uz
5-+g0n+bKGd9xi64sI55HsxAdUEFjhGS1VCn1MEdQSe+14aQYG+55nx0dokX9cRAK7
6-FdRQg7k4ZVLzPkpzpIl8aIR+XlcI1suMpGKWP3S7CueKtyQAHKG6lzd5wjZ813/g
7-am7aFxufWuDLgXYKG0wXo2WBICyr0VE8gMekuvlZsq6eXh41XVzH0f3sw7aVihGf
8-l0Jej7FfjpyuySCFwD8wH45yMEHi8ApOwwchVVNFLTucLpNcGtb+gO7N3oi0e9SH
9-wXHalJCA6nWi2Go6evqqDHNeVAoGa2pEIamTLLVFMjuDfcKSstuzTWU4Fl5PHA4=
10-=Xitc
4+iQEcBAABAgAGBQJUmO2aAAoJEHqIsNfmElEVnf8IAKKrd4jhNxNzH+QD43ef2TUO
5+pFpchf+XXEzcOql0AsIvWNsdc9+rNerUjPtfU1QBtmiUYRoZL8l3YefX0T+lLWLn
6+vsY2h5jUqdwOhAm1cbcPHZDU+bDL2kgxF6ujhRD8BWbrTlDrWGH6tkZieHn0DVLR
7+KTqzcGTw6KAHuuog9VHReRMkyAJcgyj0Wk/sQbdlJSf6+hh3l0dSymMtROEc5fYs
8+DrXKesODd+ieBb5iF/Cmo2aJ8C05fLd9P2KE/Uzi5W7X9AQeEUawaDuPQxEjHXqn
9+u8po/DtWbRl4zHxC22Knd56YTf+ui9T1Xpmrt/eBbmJYAMAWRBj9fNOo8dPNUU8=
10+=Pzo9
1111 -----END PGP SIGNATURE-----
--- trunk/jsonic-1.3/test/net/arnx/jsonic/JSONBugTest.java (revision 1852)
+++ trunk/jsonic-1.3/test/net/arnx/jsonic/JSONBugTest.java (revision 1853)
@@ -3,6 +3,7 @@
33 import static org.junit.Assert.assertEquals;
44
55 import java.lang.reflect.Type;
6+import java.util.List;
67
78 import org.junit.Test;
89
@@ -51,6 +52,12 @@
5152 assertEquals("{\"str\":\"\",\"num\":null,\"bool\":null}", json.format(new PreformatNullBean()));
5253 }
5354
55+ @Test
56+ public void testGenerics() {
57+ Sample<Address> aList = JSON.decode("{items: [{name: 'a'}]}", new TypeReference<Sample<Address>>(){});
58+ Address address = aList.getItems().get(0);
59+ }
60+
5461 public static class TestClass {
5562 @JSONHint(type = SubClass.class)
5663 public SuperClass test = new SubClass();
@@ -154,4 +161,25 @@
154161
155162 public Boolean bool;
156163 }
164+
165+ class Address {
166+ private String name;
167+ public String getName() {
168+ return name;
169+ }
170+ public void setName(String name) {
171+ this.name = name;
172+ }
173+ }
174+
175+ class Sample<T> {
176+ private List<T> items;
177+
178+ public List<T> getItems() {
179+ return items;
180+ }
181+ public void setItems(List<T> items) {
182+ this.items = items;
183+ }
184+ }
157185 }
--- trunk/jsonic-1.3/test/net/arnx/jsonic/JSONGenericsTest.java (revision 1852)
+++ trunk/jsonic-1.3/test/net/arnx/jsonic/JSONGenericsTest.java (revision 1853)
@@ -2,9 +2,11 @@
22
33 import static org.junit.Assert.*;
44
5+import java.math.BigDecimal;
56 import java.util.ArrayList;
67 import java.util.Date;
78 import java.util.LinkedHashMap;
9+import java.util.List;
810
911 import org.junit.Test;
1012
@@ -16,20 +18,123 @@
1618 InheritMap<Integer, Date> map = new InheritMap<Integer, Date>();
1719 map.put(new Date(1000000), 20);
1820 list.add(map);
19-
21+
2022 assertEquals(list, JSON.decode(JSON.encode(list), new TypeReference<InheritList>() {}));
2123 }
22-
23-
24+
25+
2426 public static class InheritList extends ArrayList<InheritMap<Integer, Date>> {
25-
27+
2628 }
27-
29+
2830 public static class InheritMap<V, Y> extends LinkedHashMap<Y, V> implements ImplTest<Y> {
29-
31+
3032 }
31-
33+
3234 public static interface ImplTest<X> {
33-
35+
3436 }
37+
38+ @Test
39+ public void testParameterizedType() {
40+ ParameterizedTypeBean<ValueBean> bean = new ParameterizedTypeBean<ValueBean>();
41+ bean.valueProp = new ValueBean();
42+ bean.valueProp.value = "test";
43+ bean.listProp = new ArrayList<ValueBean>();
44+ bean.listProp.add(new ValueBean());
45+ bean.listProp.get(0).value = "test";
46+
47+ assertEquals(bean, JSON.decode(JSON.encode(bean), new TypeReference<ParameterizedTypeBean<ValueBean>>() {}));
48+
49+ ParameterizedTypeBean<ParameterizedTypeBean<ValueBean>> bean2 = new ParameterizedTypeBean<ParameterizedTypeBean<ValueBean>>();
50+ bean2.valueProp = bean;
51+ bean2.listProp = new ArrayList<ParameterizedTypeBean<ValueBean>>();
52+ bean2.listProp.add(bean);
53+
54+ assertEquals(bean2, JSON.decode(JSON.encode(bean2), new TypeReference<ParameterizedTypeBean<ParameterizedTypeBean<ValueBean>>>() {}));
55+ }
56+
57+ public static class ParameterizedTypeBean<T> {
58+ public T valueProp;
59+ public List<T> listProp;
60+
61+ public ParameterizedTypeBean() {
62+ }
63+
64+ @Override
65+ public int hashCode() {
66+ final int prime = 31;
67+ int result = 1;
68+ result = prime * result
69+ + ((valueProp == null) ? 0 : valueProp.hashCode());
70+ result = prime * result
71+ + ((listProp == null) ? 0 : listProp.hashCode());
72+ return result;
73+ }
74+
75+ @Override
76+ public boolean equals(Object obj) {
77+ if (this == obj)
78+ return true;
79+ if (obj == null)
80+ return false;
81+ if (getClass() != obj.getClass())
82+ return false;
83+ ParameterizedTypeBean<?> other = (ParameterizedTypeBean<?>) obj;
84+ if (valueProp == null) {
85+ if (other.valueProp != null)
86+ return false;
87+ } else if (!valueProp.equals(other.valueProp))
88+ return false;
89+ if (listProp == null) {
90+ if (other.listProp != null)
91+ return false;
92+ } else if (!listProp.equals(other.listProp))
93+ return false;
94+ return true;
95+ }
96+
97+ @Override
98+ public String toString() {
99+ return "ParameterizedTypeBean [valueProp=" + valueProp
100+ + ", listProp=" + listProp + "]";
101+ }
102+ }
103+
104+ public static class ValueBean {
105+ public String value;
106+
107+ public ValueBean() {
108+ }
109+
110+ @Override
111+ public int hashCode() {
112+ final int prime = 31;
113+ int result = 1;
114+ result = prime * result + ((value == null) ? 0 : value.hashCode());
115+ return result;
116+ }
117+
118+ @Override
119+ public boolean equals(Object obj) {
120+ if (this == obj)
121+ return true;
122+ if (obj == null)
123+ return false;
124+ if (getClass() != obj.getClass())
125+ return false;
126+ ValueBean other = (ValueBean) obj;
127+ if (value == null) {
128+ if (other.value != null)
129+ return false;
130+ } else if (!value.equals(other.value))
131+ return false;
132+ return true;
133+ }
134+
135+ @Override
136+ public String toString() {
137+ return "ValueBean [value=" + value + "]";
138+ }
139+ }
35140 }
--- trunk/jsonic-1.3/src/net/arnx/jsonic/util/LocalCache.java (revision 1852)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/util/LocalCache.java (revision 1853)
@@ -39,7 +39,7 @@
3939 private String[] stringCache;
4040 private Map<String, DateFormat> dateFormatCache;
4141 private Map<String, NumberFormat> numberFormatCache;
42- private Map<ParameterTypeKey, Type> parameterTypeCache;
42+ private Map<ParameterTypeKey, Type> paramTypeCache;
4343
4444 public LocalCache(String bundle, Locale locale, TimeZone timeZone) {
4545 this.resources = ResourceBundle.getBundle(bundle, locale);
@@ -125,17 +125,17 @@
125125 return dformat;
126126 }
127127
128- public Type getParameterType(Type t, Class<?> cls, int pos) {
129- ParameterTypeKey key = new ParameterTypeKey(t, cls, pos);
128+ public Type getResolvedType(Type ptype, Class<?> pcls, Type type) {
129+ ParameterTypeKey key = new ParameterTypeKey(ptype, pcls, type);
130130 Type result = null;
131- if (parameterTypeCache == null) {
132- parameterTypeCache = new HashMap<ParameterTypeKey, Type>();
131+ if (paramTypeCache == null) {
132+ paramTypeCache = new HashMap<ParameterTypeKey, Type>();
133133 } else {
134- result = parameterTypeCache.get(key);
134+ result = paramTypeCache.get(key);
135135 }
136136 if (result == null) {
137- result = ClassUtil.getParameterType(t, cls, pos);
138- parameterTypeCache.put(key, result);
137+ result = ClassUtil.getResolvedType(ptype, pcls, type);
138+ paramTypeCache.put(key, result);
139139 }
140140 return result;
141141 }
@@ -153,14 +153,14 @@
153153 }
154154
155155 private static class ParameterTypeKey {
156- private Type t;
157- private Class<?> cls;
158- private int pos;
156+ private Type ptype;
157+ private Class<?> pcls;
158+ private Type type;
159159
160- public ParameterTypeKey(Type t, Class<?> cls, int pos) {
161- this.t = t;
162- this.cls = cls;
163- this.pos = pos;
160+ public ParameterTypeKey(Type ptype, Class<?> pcls, Type type) {
161+ this.ptype = ptype;
162+ this.pcls = pcls;
163+ this.type = type;
164164 }
165165
166166 @Override
@@ -167,9 +167,9 @@
167167 public int hashCode() {
168168 final int prime = 31;
169169 int result = 1;
170- result = prime * result + ((cls == null) ? 0 : cls.hashCode());
171- result = prime * result + pos;
172- result = prime * result + ((t == null) ? 0 : t.hashCode());
170+ result = prime * result + ((ptype == null) ? 0 : ptype.hashCode());
171+ result = prime * result + ((pcls == null) ? 0 : pcls.hashCode());
172+ result = prime * result + ((type == null) ? 0 : type.hashCode());
173173 return result;
174174 }
175175
@@ -182,17 +182,20 @@
182182 if (getClass() != obj.getClass())
183183 return false;
184184 ParameterTypeKey other = (ParameterTypeKey) obj;
185- if (cls == null) {
186- if (other.cls != null)
185+ if (ptype == null) {
186+ if (other.ptype != null)
187187 return false;
188- } else if (!cls.equals(other.cls))
188+ } else if (!ptype.equals(other.ptype))
189189 return false;
190- if (pos != other.pos)
190+ if (pcls == null) {
191+ if (other.pcls != null)
192+ return false;
193+ } else if (!pcls.equals(other.pcls))
191194 return false;
192- if (t == null) {
193- if (other.t != null)
195+ if (type == null) {
196+ if (other.type != null)
194197 return false;
195- } else if (!t.equals(other.t))
198+ } else if (!type.equals(other.type))
196199 return false;
197200 return true;
198201 }
--- trunk/jsonic-1.3/src/net/arnx/jsonic/util/ClassUtil.java (revision 1852)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/util/ClassUtil.java (revision 1853)
@@ -1,12 +1,12 @@
1-/*
1+/*
22 * Copyright 2014 Hidekatsu Izuno
3- *
3+ *
44 * Licensed under the Apache License, Version 2.0 (the "License");
55 * you may not use this file except in compliance with the License.
66 * You may obtain a copy of the License at
7- *
7+ *
88 * http://www.apache.org/licenses/LICENSE-2.0
9- *
9+ *
1010 * Unless required by applicable law or agreed to in writing, software
1111 * distributed under the License is distributed on an "AS IS" BASIS,
1212 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -35,13 +35,12 @@
3535 import java.util.LinkedHashMap;
3636 import java.util.Map;
3737 import java.util.WeakHashMap;
38-
3938 import java.io.ObjectStreamClass;
4039
4140 public final class ClassUtil {
42- private static final Map<ClassLoader, Map<String, Class<?>>> cache =
41+ private static final Map<ClassLoader, Map<String, Class<?>>> cache =
4342 new WeakHashMap<ClassLoader, Map<String, Class<?>>>();
44-
43+
4544 public static Class<?> findClass(String name) {
4645 ClassLoader cl;
4746 try {
@@ -49,11 +48,11 @@
4948 } catch (SecurityException e) {
5049 cl = null;
5150 }
52-
51+
5352 Map<String, Class<?>> map;
5453 synchronized (cache) {
5554 map = cache.get(cl);
56-
55+
5756 if (map == null) {
5857 map = new LinkedHashMap<String, Class<?>>(16, 0.75f, true) {
5958 protected boolean removeEldestEntry(Map.Entry<String, Class<?>> eldest) {
@@ -80,13 +79,13 @@
8079 return map.get(name);
8180 }
8281 }
83-
82+
8483 public static void clear() {
8584 synchronized (cache) {
8685 cache.clear();
8786 }
8887 }
89-
88+
9089 public static String toUpperCamel(String name) {
9190 StringBuilder sb = new StringBuilder(name.length());
9291 boolean toUpperCase = true;
@@ -103,7 +102,7 @@
103102 }
104103 return sb.toString();
105104 }
106-
105+
107106 public static String toLowerCamel(String name) {
108107 StringBuilder sb = new StringBuilder(name.length());
109108 boolean toUpperCase = false;
@@ -123,7 +122,7 @@
123122 }
124123 return sb.toString();
125124 }
126-
125+
127126 public static Class<?> getRawType(Type t) {
128127 if (t instanceof Class<?>) {
129128 return (Class<?>)t;
@@ -144,49 +143,43 @@
144143 return Object.class;
145144 }
146145 }
147-
148- public static ParameterizedType resolveParameterizedType(Type t, Class<?> baseClass) {
149- Class<?> raw = getRawType(t);
150-
151- if (t instanceof ParameterizedType && baseClass.isAssignableFrom(raw)) {
152- return (ParameterizedType)t;
153- }
154-
155- ParameterizedType pt = null;
156- if (raw.getSuperclass() != null && raw.getSuperclass() != Object.class) {
157- pt = resolveParameterizedType(raw.getGenericSuperclass(), baseClass);
158- if (pt != null) return pt;
159- }
160- if (!raw.isInterface()) {
161- for (Type ifs : raw.getGenericInterfaces()) {
162- pt = resolveParameterizedType(ifs, baseClass);
163- if (pt != null) return pt;
164- }
165- }
166- return null;
167- }
168-
169- public static Type getParameterType(Type t, Class<?> base, int pos) {
170- Class<?> c = ClassUtil.getRawType(t);
171- if (!base.isAssignableFrom(c)) return null;
172-
146+
147+ public static Type getResolvedType(Type ptype, Class<?> pcls, Type type) {
173148 Map<Type, Type> map = new HashMap<Type, Type>();
174- collectTypeVariableMap(t, c, map);
175-
176- TypeVariable<?> current = base.getTypeParameters()[pos];
149+ collectTypeVariableMap(ptype, pcls, map);
150+
177151 Type result;
178- do {
179- result = map.get(current);
180- if (result instanceof TypeVariable<?>) {
181- current = (TypeVariable<?>)result;
182- } else {
183- break;
152+ if (type instanceof ParameterizedType) {
153+ ParameterizedType paramType = (ParameterizedType)type;
154+ Type[] paramTypeArgs = paramType.getActualTypeArguments();
155+ for (int i = 0; i < paramTypeArgs.length; i++) {
156+ Type iresult = paramTypeArgs[i];
157+ while (iresult instanceof TypeVariable<?>) {
158+ Type next = map.get(iresult);
159+ if (next != null) {
160+ iresult = next;
161+ } else {
162+ break;
163+ }
164+ }
165+ paramTypeArgs[i] = iresult;
184166 }
185- } while (current != null);
186-
167+ result = new ParameterizedTypeImpl(paramType, paramTypeArgs);
168+ } else {
169+ result = type;
170+ while (result instanceof TypeVariable<?>) {
171+ Type next = map.get(result);
172+ if (next != null) {
173+ result = next;
174+ } else {
175+ break;
176+ }
177+ }
178+ }
179+
187180 return result;
188181 }
189-
182+
190183 private static void collectTypeVariableMap(Type t, Class<?> c, Map<Type, Type> map) {
191184 if (t instanceof ParameterizedType) {
192185 TypeVariable<?>[] vs = c.getTypeParameters();
@@ -196,7 +189,7 @@
196189 map.put(vs[i], as[i]);
197190 }
198191 }
199-
192+
200193 Type ot = ((ParameterizedType)t).getOwnerType();
201194 if (ot instanceof ParameterizedType) {
202195 vs = ClassUtil.getRawType(ot).getTypeParameters();
@@ -208,15 +201,15 @@
208201 }
209202 }
210203 }
211-
204+
212205 Type[] its = c.getGenericInterfaces();
213206 if (its != null) {
214207 for (Type it : its) {
215- Class<?> ic = ClassUtil.getRawType(it);
208+ Class<?> ic = ClassUtil.getRawType(it);
216209 collectTypeVariableMap(it, ic, map);
217210 }
218211 }
219-
212+
220213 Type st = c.getGenericSuperclass();
221214 while (st != null && st != Object.class) {
222215 Class<?> sc = ClassUtil.getRawType(st);
@@ -224,7 +217,7 @@
224217 st = sc.getGenericSuperclass();
225218 }
226219 }
227-
220+
228221 public static byte[] serialize(Object o) throws ObjectStreamException {
229222 ByteArrayOutputStream array = new ByteArrayOutputStream();
230223 ObjectOutputStream out = null;
@@ -239,7 +232,7 @@
239232 }
240233 return array.toByteArray();
241234 }
242-
235+
243236 public static Object deserialize(byte[] data) throws ObjectStreamException, ClassNotFoundException {
244237 Object ret = null;
245238 ObjectInputStream in = null;
@@ -254,21 +247,21 @@
254247 }
255248 return ret;
256249 }
257-
250+
258251 public static int hashCode(Object target) {
259252 if (target == null) return 0;
260253 final int prime = 31;
261254 int result = 1;
262-
255+
263256 Class<?> current = target.getClass();
264257 do {
265258 for (Field f : current.getDeclaredFields()) {
266- if (Modifier.isStatic(f.getModifiers())
259+ if (Modifier.isStatic(f.getModifiers())
267260 || Modifier.isTransient(f.getModifiers())
268261 || f.isSynthetic()) {
269262 continue;
270263 }
271-
264+
272265 Object self;
273266 try {
274267 f.setAccessible(true);
@@ -301,29 +294,29 @@
301294 } else {
302295 result = prime * result + self.hashCode();
303296 }
304-
297+
305298 System.out.println(f.getName() + ": " + result);
306299 }
307300 current = current.getSuperclass();
308301 } while (current != Object.class);
309-
302+
310303 return result;
311304 }
312-
305+
313306 public static boolean equals(Object target, Object o) {
314307 if (target == o) return true;
315308 if (target == null || o == null) return false;
316309 if (target.getClass() != o.getClass()) return false;
317-
310+
318311 Class<?> current = target.getClass();
319312 do {
320313 for (Field f : current.getDeclaredFields()) {
321- if (Modifier.isStatic(f.getModifiers())
314+ if (Modifier.isStatic(f.getModifiers())
322315 || Modifier.isTransient(f.getModifiers())
323316 || f.isSynthetic()) {
324317 continue;
325318 }
326-
319+
327320 Object self;
328321 Object other;
329322 try {
@@ -361,21 +354,21 @@
361354 }
362355 current = current.getSuperclass();
363356 } while (current != Object.class);
364-
357+
365358 return true;
366359 }
367-
360+
368361 public static String toString(Object target) {
369362 if (target == null) return "null";
370-
363+
371364 BeanInfo info = BeanInfo.get(target.getClass());
372-
365+
373366 StringBuilder sb = new StringBuilder(10 * info.getProperties().size() + 20);
374367 sb.append(target.getClass().getSimpleName()).append(" [");
375368 boolean first = true;
376369 for (PropertyInfo prop : info.getProperties()) {
377370 if (!prop.isReadable() || prop.getName().equals("class")) continue;
378-
371+
379372 if (!first) {
380373 sb.append(", ");
381374 } else {
@@ -412,18 +405,18 @@
412405 }
413406 }
414407 sb.append("]");
415-
408+
416409 return sb.toString();
417410 }
418-
411+
419412 private ClassUtil() {
420413 }
421-
414+
422415 private static class ContextObjectInputStream extends ObjectInputStream {
423416 public ContextObjectInputStream(InputStream in) throws IOException {
424417 super(in);
425418 }
426-
419+
427420 @Override
428421 protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
429422 ClassLoader cl = Thread.currentThread().getContextClassLoader();
@@ -434,4 +427,58 @@
434427 }
435428 }
436429 }
430+
431+ private static class ParameterizedTypeImpl implements ParameterizedType {
432+ private ParameterizedType parent;
433+ private Type[] args;
434+
435+ public ParameterizedTypeImpl(ParameterizedType parent, Type[] args) {
436+ this.parent = parent;
437+ this.args = args;
438+ }
439+
440+ @Override
441+ public Type[] getActualTypeArguments() {
442+ return args;
443+ }
444+
445+ @Override
446+ public Type getRawType() {
447+ return parent.getRawType();
448+ }
449+
450+ @Override
451+ public Type getOwnerType() {
452+ return parent.getOwnerType();
453+ }
454+
455+ @Override
456+ public int hashCode() {
457+ final int prime = 31;
458+ int result = 1;
459+ result = prime * result
460+ + ((parent == null) ? 0 : parent.hashCode());
461+ result = prime * result + Arrays.hashCode(args);
462+ return result;
463+ }
464+
465+ @Override
466+ public boolean equals(Object obj) {
467+ if (this == obj)
468+ return true;
469+ if (obj == null)
470+ return false;
471+ if (getClass() != obj.getClass())
472+ return false;
473+ ParameterizedTypeImpl other = (ParameterizedTypeImpl) obj;
474+ if (parent == null) {
475+ if (other.parent != null)
476+ return false;
477+ } else if (!parent.equals(other.parent))
478+ return false;
479+ if (!Arrays.equals(args, other.args))
480+ return false;
481+ return true;
482+ }
483+ }
437484 }
--- trunk/jsonic-1.3/src/net/arnx/jsonic/Converter.java (revision 1852)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/Converter.java (revision 1853)
@@ -1352,6 +1352,13 @@
13521352 final class CollectionConverter implements Converter {
13531353 public static final CollectionConverter INSTANCE = new CollectionConverter();
13541354
1355+ private static final TypeVariable<?> TYPE_VARIABLE;
1356+
1357+ static {
1358+ TypeVariable<?>[] params = Collection.class.getTypeParameters();
1359+ TYPE_VARIABLE = params[0];
1360+ }
1361+
13551362 @Override
13561363 public boolean accept(Class<?> cls) {
13571364 return Collection.class.isAssignableFrom(cls);
@@ -1363,7 +1370,7 @@
13631370 return null;
13641371 }
13651372
1366- Type pt = context.getParameterType(t, Collection.class, 0);
1373+ Type pt = context.getResolvedType(t, c, TYPE_VARIABLE);
13671374 Class<?> pc = ClassUtil.getRawType(pt);
13681375 JSONHint hint = context.getHint();
13691376
@@ -1489,6 +1496,15 @@
14891496 final class MapConverter implements Converter {
14901497 public static final MapConverter INSTANCE = new MapConverter();
14911498
1499+ private static final TypeVariable<?> TYPE_VARIABLE_KEY;
1500+ private static final TypeVariable<?> TYPE_VARIABLE_VALUE;
1501+
1502+ static {
1503+ TypeVariable<?>[] params = Map.class.getTypeParameters();
1504+ TYPE_VARIABLE_KEY = params[0];
1505+ TYPE_VARIABLE_VALUE = params[1];
1506+ }
1507+
14921508 @Override
14931509 public boolean accept(Class<?> cls) {
14941510 return Map.class.isAssignableFrom(cls);
@@ -1500,8 +1516,8 @@
15001516 return null;
15011517 }
15021518
1503- Type pt0 = context.getParameterType(t, Map.class, 0);
1504- Type pt1 = context.getParameterType(t, Map.class, 1);
1519+ Type pt0 = context.getResolvedType(t, c, TYPE_VARIABLE_KEY);
1520+ Type pt1 = context.getResolvedType(t, c, TYPE_VARIABLE_VALUE);
15051521 Class<?> pc0 = ClassUtil.getRawType(pt0);
15061522 Class<?> pc1 = ClassUtil.getRawType(pt1);
15071523
@@ -1594,13 +1610,13 @@
15941610
15951611 JSONHint hint = target.getWriteAnnotation(JSONHint.class);
15961612 context.enter(name, hint);
1597- Class<?> cls = target.getWriteType();
1598- Type gtype = target.getWriteGenericType();
1599- if (gtype instanceof TypeVariable<?> && t instanceof ParameterizedType) {
1600- gtype = resolveTypeVariable((TypeVariable<?>)gtype, (ParameterizedType)t);
1601- cls = ClassUtil.getRawType(gtype);
1613+ Type ttype = target.getWriteGenericType();
1614+ Class<?> tcls = target.getWriteType();
1615+ if (ttype != tcls && t instanceof ParameterizedType) {
1616+ ttype = context.getResolvedType(t, c, ttype);
1617+ tcls = ClassUtil.getRawType(ttype);
16021618 }
1603- target.set(o, context.postparseInternal(entry.getValue(), cls, gtype));
1619+ target.set(o, context.postparseInternal(entry.getValue(), tcls, ttype));
16041620 context.exit();
16051621 }
16061622 return o;
@@ -2347,6 +2363,8 @@
23472363 }
23482364
23492365 final class OptionalConverter implements Converter {
2366+ private static final TypeVariable<?> GENERICS_TYPE = Optional.class.getTypeParameters()[0];
2367+
23502368 public OptionalConverter() {
23512369 }
23522370
@@ -2360,7 +2378,7 @@
23602378 return Optional.empty();
23612379 }
23622380
2363- t = ClassUtil.getParameterType(t, c, 0);
2381+ t = ClassUtil.getResolvedType(t, c, GENERICS_TYPE);
23642382 value = context.convertInternal(value, ClassUtil.getRawType(t), t);
23652383 if (value != null) {
23662384 return Optional.of(value);
--- trunk/jsonic-1.3/src/net/arnx/jsonic/JSON.java (revision 1852)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/JSON.java (revision 1853)
@@ -1608,8 +1608,8 @@
16081608 return (hint != null && hint.format().length() > 0) ? hint.format() : dateFormat;
16091609 }
16101610
1611- Type getParameterType(Type t, Class<?> cls, int pos) {
1612- return getLocalCache().getParameterType(t, cls, pos);
1611+ Type getResolvedType(Type ptype, Class<?> pcls, Type type) {
1612+ return getLocalCache().getResolvedType(ptype, pcls, type);
16131613 }
16141614
16151615 @Override
--- trunk/jsonic-1.3/docs/index.html (revision 1852)
+++ trunk/jsonic-1.3/docs/index.html (revision 1853)
@@ -869,6 +869,7 @@
869869
870870 <h3>2015/5/4 version 1.3.8</h3>
871871 <ul>
872+<li>[不具合修正] パラメータを持つ総称型のプロパティの decode/parse に対応しました[チケット:#35153]</li>
872873 <li>[機能追加] Java8 の Optional 型(OptionalInt、OptionalLong、OptionalDouble、Optional)に対応しました。</li>
873874 </ul>
874875
旧リポジトリブラウザで表示