• R/O
  • SSH
  • HTTPS

jsonic: コミット


コミットメタ情報

リビジョン1861 (tree)
日時2015-08-01 16:48:15
作者hizuno

ログメッセージ

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

変更サマリ

差分

--- trunk/jsonic-1.3/docs/index.html (revision 1860)
+++ trunk/jsonic-1.3/docs/index.html (revision 1861)
@@ -640,7 +640,9 @@
640640
641641 <h3 id="format">■ 日時/数値書式の指定 <span class="subtitle">- setDateFormat/setNumberFormat</span></h3>
642642
643-<p>日付型や数値型は、デフォルトではJSON numberとして出力されますが、JSONIC 1.2.8以降ではsetDateFormat/setNumberFormatを指定することでデフォルトの日時/数値書式を設定できます。フォーマットの書式はそれぞれjava.text.DecimalFormat、java.text.SimpleDateFormatを参照してください(※8)。なお、書式は JSONHint を使うことで上書きすることができます。</p>
643+<p>日付型や数値型は、デフォルトではJSON numberとして出力されますが、JSONIC 1.2.8以降ではsetDateFormat/setNumberFormat
644+を指定することでデフォルトの日時/数値書式を設定できます。フォーマットの書式は Number型の場合 java.text.DecimalFormat、Date型の場合 java.text.SimpleDateFormat(※8)、
645+Java8 Date/Time API の場合 java.time.format.DateTimeFormatter に従ってフォーマットされます。書式は JSONHint を使うことで上書きすることができます。</p>
644646 <pre class="source">
645647 JSON json = new JSON();
646648 <span class="comment">// デフォルトの日時書式を指定</span>
@@ -867,8 +869,9 @@
867869
868870 <h2 id="releasenote">リリースノート</h2>
869871
870-<h3>2015/7/23 version 1.3.9</h3>
872+<h3>2015/7/25 version 1.3.9 ベータ1</h3>
871873 <ul>
874+<li>[不具合修正] Java8 Date/Time API に JSONHint の format が正しく反映されない問題を修正しました[チケット:#35349]</li>
872875 <li>[機能追加] Java7 の java.nio.Path 型に対応しました。</li>
873876 </ul>
874877
--- trunk/jsonic-1.3/test/net/arnx/jsonic/JSONJava8Test.java (revision 1860)
+++ trunk/jsonic-1.3/test/net/arnx/jsonic/JSONJava8Test.java (revision 1861)
@@ -5,6 +5,7 @@
55 import java.math.BigDecimal;
66 import java.nio.file.Path;
77 import java.nio.file.Paths;
8+import java.time.DayOfWeek;
89 import java.time.Duration;
910 import java.time.Instant;
1011 import java.time.LocalDate;
@@ -32,13 +33,14 @@
3233 @Test
3334 public void testEncode() {
3435 Java8DataTimeAPIBean bean = new Java8DataTimeAPIBean();
36+ bean.dayOfWeek = DayOfWeek.of(3);
3537 bean.duration = Duration.ofDays(3L);
3638 bean.instant = Instant.from(ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z")));
3739 bean.localDate = LocalDate.of(2010, 3, 3);
3840 bean.localDateTime = LocalDateTime.of(2010, 3, 3, 2, 2, 2, 2);
39- bean.localTime = LocalTime.of(2, 2, 2);
41+ bean.localTime = LocalTime.of(2, 2, 2, 2);
4042 bean.monthDay = MonthDay.of(2, 2);
41- bean.offsetDateTimey = OffsetDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
43+ bean.offsetDateTime = OffsetDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
4244 bean.offsetTime = OffsetTime.of(2, 2, 2, 2, ZoneOffset.of("Z"));
4345 bean.period = Period.of(1, 1, 3);
4446 bean.year = Year.of(2010);
@@ -47,16 +49,16 @@
4749 bean.zonedDateTime = ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
4850 bean.zoneId = ZoneId.of("UTC");
4951 bean.zonedOffset = ZoneOffset.of("Z");
50-
5152 assertEquals("{"
53+ + "\"dayOfWeek\":\"WEDNESDAY\","
5254 + "\"duration\":\"PT72H\","
5355 + "\"instant\":\"2010-03-03T02:02:02.000000002Z\","
5456 + "\"localDate\":\"2010-03-03\","
5557 + "\"localDateTime\":\"2010-03-03T02:02:02.000000002\","
56- + "\"localTime\":\"02:02:02\","
58+ + "\"localTime\":\"02:02:02.000000002\","
5759 + "\"month\":\"MARCH\","
5860 + "\"monthDay\":\"--02-02\","
59- + "\"offsetDateTimey\":\"2010-03-03T02:02:02.000000002Z\","
61+ + "\"offsetDateTime\":\"2010-03-03T02:02:02.000000002Z\","
6062 + "\"offsetTime\":\"02:02:02.000000002Z\","
6163 + "\"period\":\"P1Y1M3D\","
6264 + "\"year\":\"2010\","
@@ -66,6 +68,34 @@
6668 + "\"zonedOffset\":\"Z\""
6769 + "}", JSON.encode(bean));
6870
71+ Java8DataTimeAPIFormatterBean fbean = new Java8DataTimeAPIFormatterBean();
72+ fbean.instant = Instant.from(ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z")));
73+ fbean.localDate = LocalDate.of(2010, 3, 3);
74+ fbean.localDateTime = LocalDateTime.of(2010, 3, 3, 2, 2, 2, 2);
75+ fbean.localTime = LocalTime.of(2, 2, 2, 2);
76+ fbean.monthDay = MonthDay.of(2, 2);
77+ fbean.offsetDateTime = OffsetDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
78+ fbean.offsetTime = OffsetTime.of(2, 2, 2, 2, ZoneOffset.of("Z"));
79+ fbean.year = Year.of(2010);
80+ fbean.month = Month.of(3);
81+ fbean.dayOfWeek = DayOfWeek.of(3);
82+ fbean.yearMonth = YearMonth.of(2010, 3);
83+ fbean.zonedDateTime = ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
84+ assertEquals("{"
85+ + "\"dayOfWeek\":\"水\","
86+ + "\"instant\":\"2010/3/3 11:2:2.000000002\","
87+ + "\"localDate\":\"2010/3/3\","
88+ + "\"localDateTime\":\"2010/3/3 2:2:2.000000002\","
89+ + "\"localTime\":\"2:2:2.000000002\","
90+ + "\"month\":\"3月\","
91+ + "\"monthDay\":\"2/2\","
92+ + "\"offsetDateTime\":\"2010/3/3 2:2:2.000000002+0000\","
93+ + "\"offsetTime\":\"2:2:2.000000002+0000\","
94+ + "\"year\":\"2010\","
95+ + "\"yearMonth\":\"2010/3\","
96+ + "\"zonedDateTime\":\"2010/3/3 2:2:2.000000002Z\""
97+ + "}", JSON.encode(fbean));
98+
6999 Java8OptionalBean obean = new Java8OptionalBean();
70100 obean.optionalInt = OptionalInt.of(2);
71101 obean.optionalLong = OptionalLong.of(10000L);
@@ -104,31 +134,33 @@
104134 @Test
105135 public void testDecode() {
106136 Java8DataTimeAPIBean bean = new Java8DataTimeAPIBean();
137+ bean.dayOfWeek = DayOfWeek.of(3);
107138 bean.duration = Duration.ofDays(3L);
108139 bean.instant = Instant.from(ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z")));
109140 bean.localDate = LocalDate.of(2010, 3, 3);
110141 bean.localDateTime = LocalDateTime.of(2010, 3, 3, 2, 2, 2, 2);
111- bean.localTime = LocalTime.of(2, 2, 2);
142+ bean.localTime = LocalTime.of(2, 2, 2, 2);
112143 bean.monthDay = MonthDay.of(2, 2);
113- bean.offsetDateTimey = OffsetDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
144+ bean.offsetDateTime = OffsetDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
114145 bean.offsetTime = OffsetTime.of(2, 2, 2, 2, ZoneOffset.of("Z"));
115146 bean.period = Period.of(1, 1, 3);
116147 bean.year = Year.of(2010);
117148 bean.month = Month.of(3);
118149 bean.yearMonth = YearMonth.of(2010, 3);
150+ bean.dayOfWeek = DayOfWeek.WEDNESDAY;
119151 bean.zonedDateTime = ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
120152 bean.zoneId = ZoneId.of("UTC");
121153 bean.zonedOffset = ZoneOffset.of("Z");
122-
123154 assertEquals(bean, JSON.decode("{"
155+ + "\"dayOfWeek\":\"WEDNESDAY\","
124156 + "\"duration\":\"PT72H\","
125157 + "\"instant\":\"2010-03-03T02:02:02.000000002Z\","
126158 + "\"localDate\":\"2010-03-03\","
127159 + "\"localDateTime\":\"2010-03-03T02:02:02.000000002\","
128- + "\"localTime\":\"02:02:02\","
160+ + "\"localTime\":\"02:02:02.000000002\","
129161 + "\"month\":\"MARCH\","
130162 + "\"monthDay\":\"--02-02\","
131- + "\"offsetDateTimey\":\"2010-03-03T02:02:02.000000002Z\","
163+ + "\"offsetDateTime\":\"2010-03-03T02:02:02.000000002Z\","
132164 + "\"offsetTime\":\"02:02:02.000000002Z\","
133165 + "\"period\":\"P1Y1M3D\","
134166 + "\"year\":\"2010\","
@@ -138,6 +170,34 @@
138170 + "\"zonedOffset\":\"Z\""
139171 + "}", Java8DataTimeAPIBean.class));
140172
173+ Java8DataTimeAPIFormatterBean fbean = new Java8DataTimeAPIFormatterBean();
174+ fbean.instant = Instant.from(ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z")));
175+ fbean.localDate = LocalDate.of(2010, 3, 3);
176+ fbean.localDateTime = LocalDateTime.of(2010, 3, 3, 2, 2, 2, 2);
177+ fbean.localTime = LocalTime.of(2, 2, 2, 2);
178+ fbean.monthDay = MonthDay.of(2, 2);
179+ fbean.offsetDateTime = OffsetDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
180+ fbean.offsetTime = OffsetTime.of(2, 2, 2, 2, ZoneOffset.of("Z"));
181+ fbean.year = Year.of(2010);
182+ fbean.month = Month.of(3);
183+ fbean.dayOfWeek = DayOfWeek.of(3);
184+ fbean.yearMonth = YearMonth.of(2010, 3);
185+ fbean.zonedDateTime = ZonedDateTime.of(2010, 3, 3, 2, 2, 2, 2, ZoneOffset.of("Z"));
186+ assertEquals(fbean, JSON.decode("{"
187+ + "\"dayOfWeek\":\"水\","
188+ + "\"instant\":\"2010/3/3 11:2:2.000000002\","
189+ + "\"localDate\":\"2010/3/3\","
190+ + "\"localDateTime\":\"2010/3/3 2:2:2.000000002\","
191+ + "\"localTime\":\"2:2:2.000000002\","
192+ + "\"month\":\"3月\","
193+ + "\"monthDay\":\"2/2\","
194+ + "\"offsetDateTime\":\"2010/3/3 2:2:2.000000002+0000\","
195+ + "\"offsetTime\":\"2:2:2.000000002+0000\","
196+ + "\"year\":\"2010\","
197+ + "\"yearMonth\":\"2010/3\","
198+ + "\"zonedDateTime\":\"2010/3/3 2:2:2.000000002Z\""
199+ + "}", Java8DataTimeAPIFormatterBean.class));
200+
141201 Java8OptionalBean obean = new Java8OptionalBean();
142202 obean.optionalInt = OptionalInt.of(2);
143203 obean.optionalLong = OptionalLong.of(10000L);
@@ -171,7 +231,6 @@
171231 assertEquals(pbean, JSON.decode("{"
172232 + "\"path\":\".\\\\test.txt\""
173233 + "}", PathBean.class));
174-
175234 }
176235
177236 public static class Java8DataTimeAPIBean {
@@ -181,12 +240,13 @@
181240 public LocalDateTime localDateTime;
182241 public LocalTime localTime;
183242 public MonthDay monthDay;
184- public OffsetDateTime offsetDateTimey;
243+ public OffsetDateTime offsetDateTime;
185244 public OffsetTime offsetTime;
186245 public Period period;
187246 public Year year;
188247 public Month month;
189248 public YearMonth yearMonth;
249+ public DayOfWeek dayOfWeek;
190250 public ZonedDateTime zonedDateTime;
191251 public ZoneId zoneId;
192252 public ZoneOffset zonedOffset;
@@ -209,7 +269,7 @@
209269 + ((monthDay == null) ? 0 : monthDay.hashCode());
210270 result = prime
211271 * result
212- + ((offsetDateTimey == null) ? 0 : offsetDateTimey
272+ + ((offsetDateTime == null) ? 0 : offsetDateTime
213273 .hashCode());
214274 result = prime * result
215275 + ((offsetTime == null) ? 0 : offsetTime.hashCode());
@@ -219,6 +279,8 @@
219279 result = prime * result
220280 + ((yearMonth == null) ? 0 : yearMonth.hashCode());
221281 result = prime * result
282+ + ((dayOfWeek == null) ? 0 : dayOfWeek.hashCode());
283+ result = prime * result
222284 + ((zonedDateTime == null) ? 0 : zonedDateTime.hashCode());
223285 result = prime * result
224286 + ((zoneId == null) ? 0 : zoneId.hashCode());
@@ -267,10 +329,10 @@
267329 return false;
268330 } else if (!monthDay.equals(other.monthDay))
269331 return false;
270- if (offsetDateTimey == null) {
271- if (other.offsetDateTimey != null)
332+ if (offsetDateTime == null) {
333+ if (other.offsetDateTime != null)
272334 return false;
273- } else if (!offsetDateTimey.equals(other.offsetDateTimey))
335+ } else if (!offsetDateTime.equals(other.offsetDateTime))
274336 return false;
275337 if (offsetTime == null) {
276338 if (other.offsetTime != null)
@@ -292,6 +354,11 @@
292354 return false;
293355 } else if (!yearMonth.equals(other.yearMonth))
294356 return false;
357+ if (dayOfWeek == null) {
358+ if (other.dayOfWeek != null)
359+ return false;
360+ } else if (!dayOfWeek.equals(other.dayOfWeek))
361+ return false;
295362 if (zonedDateTime == null) {
296363 if (other.zonedDateTime != null)
297364 return false;
@@ -312,18 +379,162 @@
312379
313380 @Override
314381 public String toString() {
315- return "Java8DataTimeAPIBean [duration=" + duration + ", instant=" + instant
316- + ", localDate=" + localDate + ", localDateTime="
317- + localDateTime + ", localTime=" + localTime
318- + ", monthDay=" + monthDay + ", offsetDateTimey="
319- + offsetDateTimey + ", offsetTime=" + offsetTime
320- + ", period=" + period + ", year=" + year + ", month="
321- + month + ", yearMonth=" + yearMonth + ", zonedDateTime="
322- + zonedDateTime + ", zoneId=" + zoneId
382+ return "Java8DataTimeAPIBean [duration=" + duration
383+ + ", instant=" + instant
384+ + ", localDate=" + localDate
385+ + ", localDateTime=" + localDateTime
386+ + ", localTime=" + localTime
387+ + ", monthDay=" + monthDay
388+ + ", offsetDateTimey=" + offsetDateTime
389+ + ", offsetTime=" + offsetTime
390+ + ", period=" + period
391+ + ", year=" + year
392+ + ", month=" + month
393+ + ", yearMonth=" + yearMonth
394+ + ", dayOfWeek=" + dayOfWeek
395+ + ", zonedDateTime=" + zonedDateTime
396+ + ", zoneId=" + zoneId
323397 + ", zonedOffset=" + zonedOffset + "]";
324398 }
325399 }
326400
401+ public static class Java8DataTimeAPIFormatterBean {
402+ @JSONHint(format = "yyyy/M/d H:m:s.nnnnnnnnn")
403+ public Instant instant;
404+ @JSONHint(format = "yyyy/M/d")
405+ public LocalDate localDate;
406+ @JSONHint(format = "yyyy/M/d H:m:s.nnnnnnnnn")
407+ public LocalDateTime localDateTime;
408+ @JSONHint(format = "H:m:s.nnnnnnnnn")
409+ public LocalTime localTime;
410+ @JSONHint(format = "M/d")
411+ public MonthDay monthDay;
412+ @JSONHint(format = "yyyy/M/d H:m:s.nnnnnnnnnZ")
413+ public OffsetDateTime offsetDateTime;
414+ @JSONHint(format = "H:m:s.nnnnnnnnnZ")
415+ public OffsetTime offsetTime;
416+ @JSONHint(format = "yyyy")
417+ public Year year;
418+ @JSONHint(format = "MMMM")
419+ public Month month;
420+ @JSONHint(format = "E")
421+ public DayOfWeek dayOfWeek;
422+ @JSONHint(format = "yyyy/M")
423+ public YearMonth yearMonth;
424+ @JSONHint(format = "yyyy/M/d H:m:s.nnnnnnnnnz")
425+ public ZonedDateTime zonedDateTime;
426+ @Override
427+ public int hashCode() {
428+ final int prime = 31;
429+ int result = 1;
430+ result = prime * result
431+ + ((instant == null) ? 0 : instant.hashCode());
432+ result = prime * result
433+ + ((localDate == null) ? 0 : localDate.hashCode());
434+ result = prime * result
435+ + ((localDateTime == null) ? 0 : localDateTime.hashCode());
436+ result = prime * result
437+ + ((localTime == null) ? 0 : localTime.hashCode());
438+ result = prime * result
439+ + ((monthDay == null) ? 0 : monthDay.hashCode());
440+ result = prime
441+ * result
442+ + ((offsetDateTime == null) ? 0 : offsetDateTime
443+ .hashCode());
444+ result = prime * result
445+ + ((offsetTime == null) ? 0 : offsetTime.hashCode());
446+ result = prime * result + ((year == null) ? 0 : year.hashCode());
447+ result = prime * result + ((month == null) ? 0 : month.hashCode());
448+ result = prime * result + ((dayOfWeek == null) ? 0 : dayOfWeek.hashCode());
449+ result = prime * result
450+ + ((yearMonth == null) ? 0 : yearMonth.hashCode());
451+ result = prime * result
452+ + ((zonedDateTime == null) ? 0 : zonedDateTime.hashCode());
453+ return result;
454+ }
455+ @Override
456+ public boolean equals(Object obj) {
457+ if (this == obj)
458+ return true;
459+ if (obj == null)
460+ return false;
461+ if (getClass() != obj.getClass())
462+ return false;
463+ Java8DataTimeAPIFormatterBean other = (Java8DataTimeAPIFormatterBean) obj;
464+ if (instant == null) {
465+ if (other.instant != null)
466+ return false;
467+ } else if (!instant.equals(other.instant))
468+ return false;
469+ if (localDate == null) {
470+ if (other.localDate != null)
471+ return false;
472+ } else if (!localDate.equals(other.localDate))
473+ return false;
474+ if (localDateTime == null) {
475+ if (other.localDateTime != null)
476+ return false;
477+ } else if (!localDateTime.equals(other.localDateTime))
478+ return false;
479+ if (localTime == null) {
480+ if (other.localTime != null)
481+ return false;
482+ } else if (!localTime.equals(other.localTime))
483+ return false;
484+ if (monthDay == null) {
485+ if (other.monthDay != null)
486+ return false;
487+ } else if (!monthDay.equals(other.monthDay))
488+ return false;
489+ if (offsetDateTime == null) {
490+ if (other.offsetDateTime != null)
491+ return false;
492+ } else if (!offsetDateTime.equals(other.offsetDateTime))
493+ return false;
494+ if (offsetTime == null) {
495+ if (other.offsetTime != null)
496+ return false;
497+ } else if (!offsetTime.equals(other.offsetTime))
498+ return false;
499+ if (year == null) {
500+ if (other.year != null)
501+ return false;
502+ } else if (!year.equals(other.year))
503+ return false;
504+ if (month != other.month)
505+ return false;
506+ if (dayOfWeek != other.dayOfWeek)
507+ return false;
508+ if (yearMonth == null) {
509+ if (other.yearMonth != null)
510+ return false;
511+ } else if (!yearMonth.equals(other.yearMonth))
512+ return false;
513+ if (zonedDateTime == null) {
514+ if (other.zonedDateTime != null)
515+ return false;
516+ } else if (!zonedDateTime.equals(other.zonedDateTime))
517+ return false;
518+ return true;
519+ }
520+
521+ @Override
522+ public String toString() {
523+ return "Java8DataTimeAPIFormatterBean [instant=" + instant
524+ + ", localDate=" + localDate
525+ + ", localDateTime=" + localDateTime
526+ + ", localTime=" + localTime
527+ + ", monthDay=" + monthDay
528+ + ", offsetDateTimey=" + offsetDateTime
529+ + ", offsetTime=" + offsetTime
530+ + ", year=" + year
531+ + ", month=" + month
532+ + ", yearMonth=" + yearMonth
533+ + ", zonedDateTime=" + zonedDateTime
534+ + "]";
535+ }
536+ }
537+
327538 public static class Java8OptionalBean {
328539 public OptionalInt optionalInt;
329540 public OptionalLong optionalLong;
--- trunk/jsonic-1.3/src/net/arnx/jsonic/util/LocalCache.java (revision 1860)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/util/LocalCache.java (revision 1861)
@@ -37,9 +37,7 @@
3737 private StringBuilder builderCache;
3838 private int stringCacheCount = 0;
3939 private String[] stringCache;
40- private Map<String, DateFormat> dateFormatCache;
41- private Map<String, NumberFormat> numberFormatCache;
42- private Map<ParameterTypeKey, Type> paramTypeCache;
40+ private Map<Class<?>, Map<Object, Object>> formatCache;
4341
4442 public LocalCache(String bundle, Locale locale, TimeZone timeZone) {
4543 this.resources = ResourceBundle.getBundle(bundle, locale);
@@ -96,48 +94,36 @@
9694 return h & (CACHE_SIZE-1);
9795 }
9896
99- public NumberFormat getNumberFormat(String format) {
100- NumberFormat nformat = null;
101- if (numberFormatCache == null) {
102- numberFormatCache = new HashMap<String, NumberFormat>();
97+ @SuppressWarnings("unchecked")
98+ public <T> T get(Class<T> cls, Object key, Provider<T> provider) {
99+ Map<Object, Object> map = null;
100+ if (formatCache == null) {
101+ formatCache = new HashMap<Class<?>, Map<Object, Object>>();
103102 } else {
104- nformat = numberFormatCache.get(format);
103+ map = formatCache.get(cls);
105104 }
106- if (nformat == null) {
107- nformat = new DecimalFormat(format, new DecimalFormatSymbols(locale));
108- numberFormatCache.put(format, nformat);
105+ if (map == null) {
106+ map = new HashMap<Object, Object>();
107+ formatCache.put(cls, map);
109108 }
110- return nformat;
109+ Object f = map.get(key);
110+ if (f == null) {
111+ f = provider.get(key, locale, timeZone);
112+ map.put(key, f);
113+ }
114+ return (T)f;
111115 }
112116
117+ public NumberFormat getNumberFormat(String format) {
118+ return get(NumberFormat.class, format, NumberFormatProvider.INSTANCE);
119+ }
120+
113121 public DateFormat getDateFormat(String format) {
114- DateFormat dformat = null;
115- if (dateFormatCache == null) {
116- dateFormatCache = new HashMap<String, DateFormat>();
117- } else {
118- dformat = dateFormatCache.get(format);
119- }
120- if (dformat == null) {
121- dformat = new ExtendedDateFormat(format, locale);
122- dformat.setTimeZone(timeZone);
123- dateFormatCache.put(format, dformat);
124- }
125- return dformat;
122+ return get(DateFormat.class, format, DateFormatProvider.INSTANCE);
126123 }
127124
128125 public Type getResolvedType(Type ptype, Class<?> pcls, Type type) {
129- ParameterTypeKey key = new ParameterTypeKey(ptype, pcls, type);
130- Type result = null;
131- if (paramTypeCache == null) {
132- paramTypeCache = new HashMap<ParameterTypeKey, Type>();
133- } else {
134- result = paramTypeCache.get(key);
135- }
136- if (result == null) {
137- result = ClassUtil.getResolvedType(ptype, pcls, type);
138- paramTypeCache.put(key, result);
139- }
140- return result;
126+ return get(Type.class, new ParameterTypeKey(ptype, pcls, type), ResolvedTypeProvider.INSTANCE);
141127 }
142128
143129 public String getMessage(String id) {
@@ -200,4 +186,38 @@
200186 return true;
201187 }
202188 }
189+
190+ public static interface Provider<T> {
191+ public T get(Object key, Locale locale, TimeZone timeZone);
192+ }
193+
194+ private static class NumberFormatProvider implements Provider<NumberFormat> {
195+ public static final NumberFormatProvider INSTANCE = new NumberFormatProvider();
196+
197+ @Override
198+ public NumberFormat get(Object format, Locale locale, TimeZone timeZone) {
199+ return new DecimalFormat((String)format, new DecimalFormatSymbols(locale));
200+ }
201+ }
202+
203+ private static class DateFormatProvider implements Provider<DateFormat> {
204+ public static final DateFormatProvider INSTANCE = new DateFormatProvider();
205+
206+ @Override
207+ public DateFormat get(Object format, Locale locale, TimeZone timeZone) {
208+ ExtendedDateFormat dformat = new ExtendedDateFormat((String)format, locale);
209+ dformat.setTimeZone(timeZone);
210+ return dformat;
211+ }
212+ }
213+
214+ private static class ResolvedTypeProvider implements Provider<Type> {
215+ public static final ResolvedTypeProvider INSTANCE = new ResolvedTypeProvider();
216+
217+ @Override
218+ public Type get(Object o, Locale locale, TimeZone timeZone) {
219+ ParameterTypeKey key = (ParameterTypeKey)o;
220+ return ClassUtil.getResolvedType(key.ptype, key.pcls, key.type);
221+ }
222+ }
203223 }
--- trunk/jsonic-1.3/src/net/arnx/jsonic/Formatter.java (revision 1860)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/Formatter.java (revision 1861)
@@ -30,7 +30,9 @@
3030 import java.sql.Struct;
3131 import java.text.DateFormat;
3232 import java.text.NumberFormat;
33+import java.time.Instant;
3334 import java.time.ZoneId;
35+import java.time.format.DateTimeFormatter;
3436 import java.time.temporal.TemporalAccessor;
3537 import java.time.temporal.TemporalAmount;
3638 import java.util.Arrays;
@@ -1505,27 +1507,100 @@
15051507 }
15061508 }
15071509
1508-final class TemporalFormatter implements Formatter {
1509- private static final Class<?>[] targets = {
1510- TemporalAccessor.class,
1511- TemporalAmount.class,
1512- ZoneId.class
1513- };
1510+final class TemporalEnumFormatter implements Formatter {
1511+ public TemporalEnumFormatter() {
1512+ }
15141513
1515- public TemporalFormatter() {
1514+ @Override
1515+ public boolean accept(Object o) {
1516+ return o instanceof TemporalAccessor && o instanceof Enum<?>;
15161517 }
15171518
15181519 @Override
1520+ public boolean isStruct() {
1521+ return false;
1522+ }
1523+
1524+ @Override
1525+ public void format(Context context, Object src, Object o, OutputSource out) throws Exception {
1526+ String format = context.getDateFormatText();
1527+ if (format != null) {
1528+ StringFormatter.serialize(context, context.getLocalCache()
1529+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE)
1530+ .format((TemporalAccessor)o), out);
1531+ } else if (context.getEnumStyle() != null) {
1532+ StringFormatter.serialize(context, context.getEnumStyle().to(((Enum<?>)o).name()), out);
1533+ } else {
1534+ out.append(Integer.toString(((Enum<?>)o).ordinal()));
1535+ }
1536+ }
1537+}
1538+
1539+final class InstantFormatter implements Formatter {
1540+ public InstantFormatter() {
1541+ }
1542+
1543+ @Override
15191544 public boolean accept(Object o) {
1520- for (Class<?> target : targets) {
1521- if (o != null && target.isAssignableFrom(o.getClass())) {
1522- return true;
1523- }
1545+ return o instanceof Instant;
1546+ }
1547+
1548+ @Override
1549+ public boolean isStruct() {
1550+ return false;
1551+ }
1552+
1553+ @Override
1554+ public void format(Context context, Object src, Object o, OutputSource out) throws Exception {
1555+ String format = context.getDateFormatText();
1556+ if (format != null) {
1557+ StringFormatter.serialize(context, context.getLocalCache()
1558+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE)
1559+ .withZone(context.getTimeZone().toZoneId())
1560+ .format((TemporalAccessor)o), out);
1561+ } else {
1562+ StringFormatter.serialize(context, o.toString(), out);
15241563 }
1564+ }
1565+}
1566+
1567+final class TemporalAccessorFormatter implements Formatter {
1568+ public TemporalAccessorFormatter() {
1569+ }
1570+
1571+ @Override
1572+ public boolean accept(Object o) {
1573+ return o instanceof TemporalAccessor;
1574+ }
1575+
1576+ @Override
1577+ public boolean isStruct() {
15251578 return false;
15261579 }
15271580
15281581 @Override
1582+ public void format(Context context, Object src, Object o, OutputSource out) throws Exception {
1583+ String format = context.getDateFormatText();
1584+ if (format != null) {
1585+ StringFormatter.serialize(context, context.getLocalCache()
1586+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE)
1587+ .format((TemporalAccessor)o), out);
1588+ } else {
1589+ StringFormatter.serialize(context, o.toString(), out);
1590+ }
1591+ }
1592+}
1593+
1594+final class TemporalAmountFormatter implements Formatter {
1595+ public TemporalAmountFormatter() {
1596+ }
1597+
1598+ @Override
1599+ public boolean accept(Object o) {
1600+ return o instanceof TemporalAmount;
1601+ }
1602+
1603+ @Override
15291604 public boolean isStruct() {
15301605 return false;
15311606 }
@@ -1536,7 +1611,26 @@
15361611 }
15371612 }
15381613
1614+final class ZoneIdFormatter implements Formatter {
1615+ public ZoneIdFormatter() {
1616+ }
15391617
1618+ @Override
1619+ public boolean accept(Object o) {
1620+ return o instanceof ZoneId;
1621+ }
1622+
1623+ @Override
1624+ public boolean isStruct() {
1625+ return false;
1626+ }
1627+
1628+ @Override
1629+ public void format(Context context, Object src, Object o, OutputSource out) throws Exception {
1630+ StringFormatter.serialize(context, o.toString(), out);
1631+ }
1632+}
1633+
15401634 final class OptionalIntFormatter implements Formatter {
15411635 public static final OptionalIntFormatter INSTNACE = new OptionalIntFormatter();
15421636
--- trunk/jsonic-1.3/src/net/arnx/jsonic/Converter.java (revision 1860)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/Converter.java (revision 1861)
@@ -57,6 +57,8 @@
5757 import java.time.ZoneOffset;
5858 import java.time.ZonedDateTime;
5959 import java.time.format.DateTimeFormatter;
60+import java.time.temporal.TemporalAccessor;
61+import java.time.temporal.TemporalQuery;
6062 import java.util.Calendar;
6163 import java.util.Collection;
6264 import java.util.Date;
@@ -1835,7 +1837,50 @@
18351837 } else if (value instanceof Number) {
18361838 return Instant.ofEpochMilli(((Number)value).longValue());
18371839 } else if (value instanceof String) {
1838- return Instant.parse(((String)value));
1840+ String format = context.getDateFormatText();
1841+ if (format != null) {
1842+ TemporalAccessor temp = context.getLocalCache()
1843+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE)
1844+ .parseBest((String)value,
1845+ new TemporalQuery<ZonedDateTime>() {
1846+ @Override
1847+ public ZonedDateTime queryFrom(TemporalAccessor temporal) {
1848+ return ZonedDateTime.from(temporal);
1849+ }
1850+ },
1851+ new TemporalQuery<OffsetDateTime>() {
1852+ @Override
1853+ public OffsetDateTime queryFrom(TemporalAccessor temporal) {
1854+ return OffsetDateTime.from(temporal);
1855+ }
1856+ },
1857+ new TemporalQuery<LocalDateTime>() {
1858+ @Override
1859+ public LocalDateTime queryFrom(TemporalAccessor temporal) {
1860+ return LocalDateTime.from(temporal);
1861+ }
1862+ },
1863+ new TemporalQuery<LocalDate>() {
1864+ @Override
1865+ public LocalDate queryFrom(TemporalAccessor temporal) {
1866+ return LocalDate.from(temporal);
1867+ }
1868+ });
1869+
1870+ if (temp instanceof ZonedDateTime) {
1871+ return ((ZonedDateTime)temp).toInstant();
1872+ } else if (temp instanceof OffsetDateTime) {
1873+ return ((OffsetDateTime)temp).toInstant();
1874+ } else if (temp instanceof LocalDateTime) {
1875+ return ((LocalDateTime)temp).atZone(context.getTimeZone().toZoneId()).toInstant();
1876+ } else if (temp instanceof LocalDate) {
1877+ return ((LocalDate)temp).atStartOfDay(context.getTimeZone().toZoneId()).toInstant();
1878+ } else {
1879+ return (Instant)temp;
1880+ }
1881+ } else {
1882+ return Instant.parse(((String)value));
1883+ }
18391884 } else {
18401885 throw new UnsupportedOperationException("Cannot convert " + value.getClass() + " to " + t);
18411886 }
@@ -1867,8 +1912,8 @@
18671912 } else if (value instanceof String) {
18681913 String format = context.getDateFormatText();
18691914 if (format != null) {
1870- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
1871- return LocalDate.parse(((String)value), f);
1915+ return LocalDate.parse(((String)value), context.getLocalCache()
1916+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
18721917 } else {
18731918 return LocalDate.parse(((String)value));
18741919 }
@@ -1903,8 +1948,8 @@
19031948 } else if (value instanceof String) {
19041949 String format = context.getDateFormatText();
19051950 if (format != null) {
1906- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
1907- return LocalDateTime.parse(((String)value), f);
1951+ return LocalDateTime.parse(((String)value), context.getLocalCache()
1952+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
19081953 } else {
19091954 return LocalDateTime.parse(((String)value));
19101955 }
@@ -1939,8 +1984,8 @@
19391984 } else if (value instanceof String) {
19401985 String format = context.getDateFormatText();
19411986 if (format != null) {
1942- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
1943- return LocalTime.parse(((String)value), f);
1987+ return LocalTime.parse(((String)value), context.getLocalCache()
1988+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
19441989 } else {
19451990 return LocalTime.parse(((String)value));
19461991 }
@@ -1975,8 +2020,8 @@
19752020 } else if (value instanceof String) {
19762021 String format = context.getDateFormatText();
19772022 if (format != null) {
1978- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
1979- return MonthDay.parse(((String)value), f);
2023+ return MonthDay.parse(((String)value), context.getLocalCache()
2024+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
19802025 } else {
19812026 return MonthDay.parse(((String)value));
19822027 }
@@ -2011,8 +2056,8 @@
20112056 } else if (value instanceof String) {
20122057 String format = context.getDateFormatText();
20132058 if (format != null) {
2014- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
2015- return OffsetDateTime.parse(((String)value), f);
2059+ return OffsetDateTime.parse(((String)value), context.getLocalCache()
2060+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
20162061 } else {
20172062 return OffsetDateTime.parse(((String)value));
20182063 }
@@ -2047,8 +2092,8 @@
20472092 } else if (value instanceof String) {
20482093 String format = context.getDateFormatText();
20492094 if (format != null) {
2050- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
2051- return OffsetTime.parse(((String)value), f);
2095+ return OffsetTime.parse(((String)value), context.getLocalCache()
2096+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
20522097 } else {
20532098 return OffsetTime.parse(((String)value));
20542099 }
@@ -2115,8 +2160,8 @@
21152160 } else if (value instanceof String) {
21162161 String format = context.getDateFormatText();
21172162 if (format != null) {
2118- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
2119- return Year.parse(((String)value), f);
2163+ return Year.parse(((String)value), context.getLocalCache()
2164+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
21202165 } else {
21212166 return Year.parse(((String)value));
21222167 }
@@ -2151,8 +2196,8 @@
21512196 } else if (value instanceof String) {
21522197 String format = context.getDateFormatText();
21532198 if (format != null) {
2154- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
2155- return YearMonth.parse(((String)value), f);
2199+ return YearMonth.parse(((String)value), context.getLocalCache()
2200+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
21562201 } else {
21572202 return YearMonth.parse(((String)value));
21582203 }
@@ -2187,8 +2232,8 @@
21872232 } else if (value instanceof String) {
21882233 String format = context.getDateFormatText();
21892234 if (format != null) {
2190- DateTimeFormatter f = DateTimeFormatter.ofPattern(format, context.getLocale());
2191- return ZonedDateTime.parse(((String)value), f);
2235+ return ZonedDateTime.parse(((String)value), context.getLocalCache()
2236+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE));
21922237 } else {
21932238 return ZonedDateTime.parse(((String)value));
21942239 }
@@ -2283,7 +2328,22 @@
22832328 } else if (value instanceof Number) {
22842329 return DayOfWeek.of(((Number)value).intValue());
22852330 } else if (value instanceof String) {
2286- return DayOfWeek.valueOf(((String)value));
2331+ String text = (String)value;
2332+ String format = context.getDateFormatText();
2333+ if (format != null) {
2334+ return context.getLocalCache()
2335+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE)
2336+ .parse(text, new TemporalQuery<DayOfWeek>() {
2337+ @Override
2338+ public DayOfWeek queryFrom(TemporalAccessor temporal) {
2339+ return DayOfWeek.from(temporal);
2340+ }
2341+ });
2342+ } else if (text.length() > 0 && text.charAt(0) >= '0' && text.charAt(0) <= '9') {
2343+ return DayOfWeek.of(Integer.parseInt(text));
2344+ } else {
2345+ return DayOfWeek.valueOf(text);
2346+ }
22872347 } else {
22882348 throw new UnsupportedOperationException("Cannot convert " + value.getClass() + " to " + t);
22892349 }
@@ -2315,7 +2375,22 @@
23152375 } else if (value instanceof Number) {
23162376 return Month.of(((Number)value).intValue());
23172377 } else if (value instanceof String) {
2318- return Month.valueOf(((String)value));
2378+ String text = (String)value;
2379+ String format = context.getDateFormatText();
2380+ if (format != null) {
2381+ return context.getLocalCache()
2382+ .get(DateTimeFormatter.class, format, DateTimeFormatterProvider.INSTANCE)
2383+ .parse(text, new TemporalQuery<Month>() {
2384+ @Override
2385+ public Month queryFrom(TemporalAccessor temporal) {
2386+ return Month.from(temporal);
2387+ }
2388+ });
2389+ } else if (text.length() > 0 && text.charAt(0) >= '0' && text.charAt(0) <= '9') {
2390+ return Month.of(Integer.parseInt(text));
2391+ } else {
2392+ return Month.valueOf(text);
2393+ }
23192394 } else {
23202395 throw new UnsupportedOperationException("Cannot convert " + value.getClass() + " to " + t);
23212396 }
--- trunk/jsonic-1.3/src/net/arnx/jsonic/JSON.java (revision 1860)
+++ trunk/jsonic-1.3/src/net/arnx/jsonic/JSON.java (revision 1861)
@@ -36,6 +36,7 @@
3636 import java.text.DateFormat;
3737 import java.text.MessageFormat;
3838 import java.text.NumberFormat;
39+import java.time.format.DateTimeFormatter;
3940 import java.util.ArrayList;
4041 import java.util.Calendar;
4142 import java.util.Collection;
@@ -270,6 +271,9 @@
270271 formatter = getFormatterInstance(PACKAGE_NAME + ".PathFormatter", cl);
271272 if (formatter != null) FORMAT_LIST.add(formatter);
272273
274+ formatter = getFormatterInstance(PACKAGE_NAME + ".TemporalEnumFormatter", cl);
275+ if (formatter != null) FORMAT_LIST.add(formatter);
276+
273277 FORMAT_LIST.add(EnumFormatter.INSTANCE);
274278 FORMAT_LIST.add(MapFormatter.INSTANCE);
275279 FORMAT_LIST.add(ListFormatter.INSTANCE);
@@ -317,9 +321,18 @@
317321 formatter = getFormatterInstance(PACKAGE_NAME + ".OptionalFormatter", cl);
318322 if (formatter != null) FORMAT_LIST.add(formatter);
319323
320- formatter = getFormatterInstance(PACKAGE_NAME + ".TemporalFormatter", cl);
324+ formatter = getFormatterInstance(PACKAGE_NAME + ".InstantFormatter", cl);
321325 if (formatter != null) FORMAT_LIST.add(formatter);
322326
327+ formatter = getFormatterInstance(PACKAGE_NAME + ".TemporalAccessorFormatter", cl);
328+ if (formatter != null) FORMAT_LIST.add(formatter);
329+
330+ formatter = getFormatterInstance(PACKAGE_NAME + ".TemporalAmountFormatter", cl);
331+ if (formatter != null) FORMAT_LIST.add(formatter);
332+
333+ formatter = getFormatterInstance(PACKAGE_NAME + ".ZoneIdFormatter", cl);
334+ if (formatter != null) FORMAT_LIST.add(formatter);
335+
323336 Converter converter = null;
324337 CONVERT_MAP.put(boolean.class, BooleanConverter.INSTANCE);
325338 CONVERT_MAP.put(char.class, CharacterConverter.INSTANCE);
@@ -1787,3 +1800,12 @@
17871800 JSONHint hint;
17881801 }
17891802 }
1803+
1804+class DateTimeFormatterProvider implements LocalCache.Provider<DateTimeFormatter> {
1805+ public static final DateTimeFormatterProvider INSTANCE = new DateTimeFormatterProvider();
1806+
1807+ @Override
1808+ public DateTimeFormatter get(Object key, Locale locale, TimeZone timeZone) {
1809+ return DateTimeFormatter.ofPattern(((String)key), locale);
1810+ }
1811+}
旧リポジトリブラウザで表示