我有一个具有时间戳属性的模型:
class Model {
@JsonProperty("timestamp")
private OffsetDateTime timestamp;
}
时间戳格式如下:
2017-09-17 13:45:42.710576+02
OffsetDateTime 无法解析:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type
java.time.OffsetDateTimefrom String "2017-09-17 13:45:42.710576+02": Text '2017-09-17 13:45:42.710576+02' could not be parsed at index 10
我该如何解决这个问题?
最佳答案
您必须告诉 Jackson 日期的格式。基本上,您有 year-month-day 后跟 hour:minute:second.microseconds 和 2 位数的偏移量 (+02)。所以你的模式将是:
@JsonProperty("timestamp")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSSSSSx")
private OffsetDateTime timestamp;
看看all the date/time patterns以获得更详细的解释。
如果您想在 OffsetDateTime 中保留相同的偏移量 (+02),请不要忘记调整 DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE option为 false。
如果此选项设置为 true(在我的测试中),结果将转换为 UTC(但它实际上转换为 Jackson 中配置的任何时区):
2017-09-17T11:45:42.710576Z
如果我设置为 false,输入中使用的偏移量将被保留:
2017-09-17T13:45:42.710576+02:00
上面的代码适用于小数点后的 6 位数字。但如果这个数量不同,您可以使用可选模式,由 [] 分隔。
示例:如果输入可以有 6 位或 3 位十进制数字,我可以使用 pattern = "yyyy-MM-dd HH:mm:ss.[SSSSSS][SSS]x"。可选部分 [SSSSSS] 和 [SSS] 告诉解析器考虑 6 位或 3 位数字。
可选模式的问题在于,在序列化时,它会打印所有模式(因此它会打印两次秒的小数:6 和 3 位)。
另一种方法是创建自定义序列化器和反序列化器(通过扩展 com.fasterxml.jackson.databind.JsonSerializer 和 com.fasterxml.jackson.databind.JsonDeserializer):
public class CustomDeserializer extends JsonDeserializer<OffsetDateTime> {
private DateTimeFormatter formatter;
public CustomDeserializer(DateTimeFormatter formatter) {
this.formatter = formatter;
}
@Override
public OffsetDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
return OffsetDateTime.parse(parser.getText(), this.formatter);
}
}
public class CustomSerializer extends JsonSerializer<OffsetDateTime> {
private DateTimeFormatter formatter;
public CustomSerializer(DateTimeFormatter formatter) {
this.formatter = formatter;
}
@Override
public void serialize(OffsetDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {
gen.writeString(value.format(this.formatter));
}
}
然后您可以在 JavaTimeModule 中注册它们。如何配置这取决于您使用的环境(例如:在 Spring 中,您可以在 xml files 中配置)。作为示例,我将以编程方式执行此操作。
首先,我使用 java.time.format.DateTimeFormatterBuilder 创建格式化程序:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// date/time
.appendPattern("yyyy-MM-dd HH:mm:ss")
// optional fraction of seconds (from 0 to 9 digits)
.optionalStart().appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, true).optionalEnd()
// offset
.appendPattern("x")
// create formatter
.toFormatter();
此格式化程序接受一个可选的秒小数部分,其中包含 0 到 9 位数字。然后我使用上面的自定义类并在 ObjectMapper 中注册它们:
// set formatter in the module and register in object mapper
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(OffsetDateTime.class, new CustomSerializer(formatter));
module.addDeserializer(OffsetDateTime.class, new CustomDeserializer(formatter));
mapper.registerModule(module);
我还从字段中删除了 @JsonFormat 注释:
@JsonProperty("timestamp")
private OffsetDateTime timestamp;
现在它接受像 2017-09-17 13:45:42+02(没有小数秒)和 2017-09-17 13:45:42.71014+02 这样的值(5 位十进制数字)。它可以解析 0 到 9 位十进制数字(9 是 API 支持的最大值),并且在序列化时打印完全相同的数量。
上面的替代方案非常灵活,因为它允许在自定义类中设置格式化程序。但它也为所有 OffsetDateTime 字段设置序列化和反序列化。
如果你不想这样,你也可以创建一个带有固定格式化程序的类:
static class CustomDeserializer extends JsonDeserializer<OffsetDateTime> {
private DateTimeFormatter formatter = // create formatter as above
// deserialize method is the same
}
static class CustomSerializer extends JsonSerializer<OffsetDateTime> {
private DateTimeFormatter formatter = // create formatter as above
// serialize method is the same
}
然后,您可以使用注释 com.fasterxml.jackson.databind.annotation.JsonSerialize 和 com.fasterxml.jackson.databind.annotation 将它们添加到您想要的字段.JsonDeserialize:
@JsonProperty("timestamp")
@JsonSerialize(using = CustomSerializer.class)
@JsonDeserialize(using = CustomDeserializer.class)
private OffsetDateTime timestamp;
有了这个,你不需要在模块中注册自定义序列化器,只有注释字段会使用自定义类(其他 OffsetDateTime 字段将使用默认设置)。
关于java - jackson :解析自定义偏移日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46263773/
我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我正在使用ruby1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问
我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查