View Javadoc
1   package org.apache.fulcrum.json.gson;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.text.DateFormat;
24  import java.text.ParseException;
25  import java.util.Date;
26  
27  import com.google.gson.Gson;
28  import com.google.gson.JsonSyntaxException;
29  import com.google.gson.TypeAdapter;
30  import com.google.gson.TypeAdapterFactory;
31  import com.google.gson.reflect.TypeToken;
32  import com.google.gson.stream.JsonReader;
33  import com.google.gson.stream.JsonToken;
34  import com.google.gson.stream.JsonWriter;
35  
36  /**
37   * Adapter for Date. Although this class appears stateless, it is not.
38   * DateFormat captures its time zone and locale when it is created, which gives
39   * this class state. DateFormat isn't thread safe either, so this class has
40   * to synchronize its read and write methods.
41   */
42  public final class DateTypeAdapter extends TypeAdapter<Date> {
43    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
44      @Override
45      @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal
46      public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
47        return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null;
48      }
49    };
50    
51    // default 
52    private DateFormat customDateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);;
53    
54    public void setCustomDateFormat(DateFormat df) {
55        this.customDateFormat = df;
56    }
57    
58    public DateFormat getCustomDateFormat() {
59        return customDateFormat;
60    }
61  
62  
63    @Override public Date read(JsonReader in) throws IOException {
64      if (in.peek() == JsonToken.NULL) {
65        in.nextNull();
66        return null;
67      }
68      return deserializeToDate(in.nextString());
69    }
70  
71    private synchronized Date deserializeToDate(String json) {
72      try {
73        return customDateFormat.parse(json);
74      } catch (ParseException e) {
75        throw new JsonSyntaxException(json, e);
76      }
77    }
78  
79    @Override public synchronized void write(JsonWriter out, Date value) throws IOException {
80      if (value == null) {
81        out.nullValue();
82        return;
83      }
84      String dateFormatAsString = customDateFormat.format(value);
85      out.value(dateFormatAsString);
86    }
87  
88  }
89