Java 解析列表<;字符串>;作为JSON
我正在阅读《真实世界软件开发》一书,本章是关于编写一个Java 解析列表<;字符串>;作为JSON,java,json,jackson,gson,Java,Json,Jackson,Gson,我正在阅读《真实世界软件开发》一书,本章是关于编写一个BankStatementCSVParser,它读取的文件如下: 30-01-2017,-100, Deliveroo 30-01-2017,-50, Tesco 01-02-2017,6000, Salary 02-02-2017,2000, Royalties 02-02-2017,-4000, Rent 03-02-2017,3000, Tesco 05-02-2017,-30, Cinema 并解析每行并输出此类的对象: publi
BankStatementCSVParser
,它读取的文件如下:
30-01-2017,-100, Deliveroo
30-01-2017,-50, Tesco
01-02-2017,6000, Salary
02-02-2017,2000, Royalties
02-02-2017,-4000, Rent
03-02-2017,3000, Tesco
05-02-2017,-30, Cinema
并解析每行并输出此类的对象:
public class BankTransaction {
private final LocalDate date;
private final double amount;
private final String description;
public BankTransaction(final LocalDate date, final double amount,
final String description) {
this.date = date;
this.amount = amount;
this.description = description;
}
public LocalDate getDate() {
return date;
}
public double getAmount() {
return amount;
}
public String getDescription() {
return description;
}
}
这很好,CSV很容易(特别是因为我在复制这本书…),问题出现在本章末尾,当时我被要求在可能的情况下自己实现BankStatementJSONParser
我尝试过woth GSON和Jackson,但我无法真正获得任何示例,因为我的BankTransaction
类是不可变的,不允许设置器
我设法找到了一个可行的解决方案,但看起来很可怕:
public List<BankTransaction> parseLinesFrom(List<String> lines) {
Map<String, ?> map = new Gson().fromJson(String.join(" ", lines), Map.class);
List<?> listOfTransactions = (List<?>) map.get("transactions");
List<BankTransaction> bankTransactions = new ArrayList<>();
listOfTransactions.forEach(rawJson -> {
LinkedTreeMap<String, ?> javaJson = (LinkedTreeMap<String, ?>) rawJson;
final LocalDate localDate = LocalDate.parse(javaJson.get("date").toString(), DATE_PATTERN);
final double amount = Double.parseDouble(javaJson.get("amount").toString());
final String description = javaJson.get("description").toString();
BankTransaction newTransaction = new BankTransaction(localDate, amount, description);
bankTransactions.add(newTransaction);
});
return bankTransactions;
}
您的问题有几种不同的解决方案:
日期
字段)我个人会做第二个,只为LocalDate创建一个自定义,它在注册后由Gson自动应用。我使用了被接受的答案描述的方法,但在Jackson中,通过覆盖Jackson ObjectMapper并在构造函数中接受DateTimeFormatter,而不是在Gson中:
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper(DateTimeFormatter pattern){
SimpleModule customModule = new SimpleModule("LocalDateMapper");
customModule.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
ToStringSerializer.instance.serialize(value, gen, serializers);
}
});
customModule.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(p.getText(), pattern);
}
});
registerModule(customModule);
}
公共类CustomObjectMapper扩展了ObjectMapper{
公共CustomObjectMapper(DateTimeFormatter模式){
SimpleModule customModule=新的SimpleModule(“LocalDateMapper”);
addSerializer(LocalDate.class,新的JsonSerializer()){
@凌驾
public void serialize(LocalDate值、JsonGenerator gen、SerializerProvider序列化程序)引发IOException{
序列化(值、根、序列化器);
}
});
addDeserializer(LocalDate.class,新的JsonDeserializer(){
@凌驾
公共LocalDate反序列化(JsonParser p,DeserializationContext ctxt)抛出IOException,JsonProcessingException{
返回LocalDate.parse(p.getText(),pattern);
}
});
注册模块(customModule);
}
}用
@JsonCreator
注释构造函数和用@JsonProperty
注释其参数是否解决了您的问题?您可以直接使用jackson反序列化:objectMapper.readValue(input,List.class)
这可能是您问题的解决方案:感谢您的建议,它几乎成功了,但它看起来不喜欢日期字段,尝试添加了一些@JsonFormat,但它不断抱怨非法反射。谢谢,我照你说的做了,但是用了杰克逊。这对我来说相当复杂,但现在我觉得它不再那么神奇了:)
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper(DateTimeFormatter pattern){
SimpleModule customModule = new SimpleModule("LocalDateMapper");
customModule.addSerializer(LocalDate.class, new JsonSerializer<LocalDate>() {
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
ToStringSerializer.instance.serialize(value, gen, serializers);
}
});
customModule.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() {
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
return LocalDate.parse(p.getText(), pattern);
}
});
registerModule(customModule);
}