2016-11-18 27 views
0

我正在使用Jackson讀取API中的JSON數據,並且大部分時間我都得到一組對象,這些對象在其實現中都是相當標準的。唯一的問題是,有時日期格式爲「yyyy-MM-dd'T'HH:mm:ss.SSS'Z'」,有時格式爲「yyyy-MM-dd」,所以JSON看起來像這樣的:分析不同標準的Json日期

[ 
    { 
     'A':'Foo' 
     'B':'2016-11-03T12:35:23.032Z' 
     'C':'7' 
    }, 
    { 
     'A':'Bar' 
     'B':'2016-11-06' 
     'C':'4' 
    }, 
    { 
     'A':'Bla' 
     'B':'2016-11-07T14:42:18.832Z' 
     'C':'23' 
    }, 
    { 
     'A':'Blo' 
     'B':'2016-11-07T15:12:23.439Z' 
     'C':'9' 
    } 
] 

每次我到第二次約會,我得到一個解析器錯誤,因爲它不是在相同的格式。我試着編寫一個類,如果第一個失敗,將使用第二個DateFormat,但現在我只是得到一個NullPointerException。

public class BackupDateFormat extends DateFormat { 

    private final LinkedList<DateFormat> formats; 

    public BackupDateFormat(DateFormat... dfs) { 
     formats = new LinkedList<>(Arrays.asList(dfs)); 
    } 

    @Override 
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { 
     return formats.getFirst().format(date, toAppendTo, fieldPosition); 
    } 

    @Override 
    public Date parse(String source, ParsePosition pos) { 
     return formats.getFirst().parse(source, pos); 
    } 

    @Override 
    public Date parse(String source) throws ParseException { 
     ParseException exception = null; 
     for (DateFormat df : formats) { 
      try { 
       return df.parse(source); 
      } 
      catch (ParseException pe) { 
       exception = pe; 
      } 
     } 
     throw exception; 
    } 
} 

他是我得到的錯誤:

com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.company.api.API$Result["result"]->java.util.ArrayList[0]->com.company.models.othercompany.Record["dateTime"]) 
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:391) 
    at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1597) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:278) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) 
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:294) 
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:266) 
    at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26) 
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:485) 
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:108) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:276) 
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:140) 
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3836) 
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2860) 
    at com.mentoredata.api.API.get(API.java:56) 

這是代碼在行56:

return mapper.<List<T>>readValue(new URL(url), mapper.getTypeFactory().constructCollectionType(List.class, type)); 

有誰知道我怎麼可以解決我當前的代碼沒有得到一個空指針或在傑克遜使用兩個dateformats?

回答

1

我很難確切地說出你的問題是什麼,但是我能夠使用你的代碼工作。首先,我創建了一個POJO,代表您正試圖反序列化的對象。我有種假設你已經有一個相當的,但是這是我的:

class Obj { 
    String A; 
    Date B; 
    Integer C; 
    /* with getters/setters */ 
} 

然後,我創建了一個自定義解串器與對象映射器。這個班不太難實施。我用了你BackupDateFormat解串器的內部:

class ObjDeserializer extends JsonDeserializer<Obj> { 
    final BackupDateFormat backupDateFormat; 

    public ObjDeserializer() { 
     backupDateFormat = new BackupDateFormat(
      new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), 
      new SimpleDateFormat("yyyy-MM-dd")); 
    } 

    @Override 
    public Obj deserialize(JsonParser p, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException { 
     // create a POJO and populate with the fields from the JSON Object 
     Obj obj = new Obj(); 
     JsonNode root = p.readValueAsTree(); 
     obj.setA(root.get("A").asText("")); 
     obj.setC(root.get("C").asInt(0)); 
     try { 
      obj.setB(backupDateFormat.parse(root.get("B").asText())); 
     } catch (ParseException e) { 
      throw new IOException("Could not parse date as expected."); 
     } 
     return obj; 
    } 

} 

之後,隨着ObjectMapper註冊您的串行:

SimpleModule dateDeserializerModule = new SimpleModule(); 
// associate the custom deserializer with your POJO 
dateDeserializerModule.addDeserializer(Obj.class, new ObjDeserializer()); 
mapper.registerModule(dateDeserializerModule); 

最後,你可以看到日期是適當從此片段,其輸出解析:

List<Obj> result = mapper.readValue(input.getBytes(), mapper.getTypeFactory().constructCollectionType(List.class, Obj.class)); 
result.forEach(x->System.out.println(x.getB().toString())); 

Thu Nov 03 12:35:23 EDT 2016 Sun Nov 06 00:00:00 EDT 2016 Mon Nov 07 14:42:18 EST 2016 Mon Nov 07 15:12:23 EST 2016

如果您發現某些內置於Jackson的內容會執行此操作,我鼓勵您使用它,但有時您最終需要使用此方法提供的額外級別的自定義。希望能幫助到你。

查看下面的問題。它是相似的,但不處理多種格式。接受的答案也使用自定義解串器。

參考文獻:

Similar SO Question

Getting started with deserializers