下面列出了怎么用com.fasterxml.jackson.annotation.JsonFormat的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
DurationDeserializer deser = this;
if (format != null) {
if (format.hasLenient()) {
Boolean leniency = format.getLenient();
if (leniency != null) {
deser = deser.withLeniency(leniency);
}
}
}
return deser;
}
public void testTypeDefaults() throws Exception
{
ObjectMapper mapper = afterburnerMapperBuilder()
.withConfigOverride(Date.class,
o -> o.setFormat(JsonFormat.Value.forPattern("yyyy.dd.MM")))
.build();
// First serialize, should result in this (in UTC):
String json = mapper.writeValueAsString(new DateWrapper(0L));
assertEquals(aposToQuotes("{'value':'1970.01.01'}"), json);
// and then read back
DateWrapper w = mapper.readValue(aposToQuotes("{'value':'1981.13.3'}"), DateWrapper.class);
assertNotNull(w);
// arbitrary TimeZone, but good enough to ensure year is right
Calendar c = Calendar.getInstance();
c.setTime(w.value);
assertEquals(1981, c.get(Calendar.YEAR));
assertEquals(Calendar.MARCH, c.get(Calendar.MONTH));
}
@Test( expected = MismatchedInputException.class)
public void testStrictDeserializeFromEmptyString() throws Exception {
final String key = "date";
final ObjectMapper mapper = mapperBuilder()
.withConfigOverride(LocalDate.class,
c -> c.setFormat(JsonFormat.Value.forLeniency(false))
)
.build();
final ObjectReader objectReader = mapper.readerFor(MAP_TYPE_REF);
final String dateValAsNullStr = null;
// even with strict, null value should be deserialized without throwing an exception
String valueFromNullStr = mapper.writeValueAsString(asMap(key, dateValAsNullStr));
Map<String, LocalDate> actualMapFromNullStr = objectReader.readValue(valueFromNullStr);
assertNull(actualMapFromNullStr.get(key));
String dateValAsEmptyStr = "";
// TODO: nothing stops us from writing an empty string, maybe there should be a check there too?
String valueFromEmptyStr = mapper.writeValueAsString(asMap("date", dateValAsEmptyStr));
// with strict, deserializing an empty string is not permitted
objectReader.readValue(valueFromEmptyStr);
}
@Test ( expected = MismatchedInputException.class)
public void testStrictDeserializeFromEmptyString() throws Exception {
final String key = "OffsetDateTime";
final ObjectMapper mapper = mapperBuilder()
.withConfigOverride(OffsetDateTime.class,
o -> o.setFormat(JsonFormat.Value.forLeniency(false)))
.build();
final ObjectReader objectReader = mapper.readerFor(MAP_TYPE_REF);
String valueFromNullStr = mapper.writeValueAsString(asMap(key, null));
Map<String, OffsetDateTime> actualMapFromNullStr = objectReader.readValue(valueFromNullStr);
assertNull(actualMapFromNullStr.get(key));
String valueFromEmptyStr = mapper.writeValueAsString(asMap(key, ""));
objectReader.readValue(valueFromEmptyStr);
}
/**
* Add the common property parameters to the code builder.
*
* @param paramBuilder the code builder
* @param property the information about the property
*/
protected final void buildCommonPropertyParameters( CodeBlock.Builder paramBuilder, PropertyInfo property ) {
if ( property.getFormat().isPresent() ) {
JsonFormat format = property.getFormat().get();
if ( !Strings.isNullOrEmpty( format.pattern() ) ) {
paramBuilder.add( "\n.setPattern($S)", format.pattern() );
}
paramBuilder.add( "\n.setShape($T.$L)", Shape.class, format.shape().name() );
if ( !Strings.isNullOrEmpty( format.locale() ) && !JsonFormat.DEFAULT_LOCALE.equals( format.locale() ) ) {
logger.log( Type.WARN, "JsonFormat.locale is not supported by default" );
paramBuilder.add( "\n.setLocale($S)", format.locale() );
}
}
if ( property.getIgnoredProperties().isPresent() ) {
for ( String ignoredProperty : property.getIgnoredProperties().get() ) {
paramBuilder.add( "\n.addIgnoredProperty($S)", ignoredProperty );
}
}
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException {
if (property != null) {
JsonFormat.Value format = ctxt.getAnnotationIntrospector().findFormat((Annotated) property.getMember());
if (format != null) {
if (format.hasPattern()) {
final String pattern = format.getPattern();
final Locale locale = format.hasLocale() ? format.getLocale() : ctxt.getLocale();
DateTimeFormatter df;
if (locale == null) {
df = DateTimeFormatter.ofPattern(pattern);
} else {
df = DateTimeFormatter.ofPattern(pattern, locale);
}
return withDateFormat(df);
}
// any use for TimeZone?
}
}
return this;
}
@Test ( expected = MismatchedInputException.class)
public void testStrictDeserializeFromEmptyString() throws Exception {
final String key = "OffsetTime";
final ObjectMapper mapper = mapperBuilder()
.withConfigOverride(OffsetTime.class,
o -> o.setFormat(JsonFormat.Value.forLeniency(false)))
.build();
final ObjectReader objectReader = mapper.readerFor(MAP_TYPE_REF);
String valueFromNullStr = mapper.writeValueAsString(asMap(key, null));
Map<String, OffsetTime> actualMapFromNullStr = objectReader.readValue(valueFromNullStr);
assertNull(actualMapFromNullStr.get(key));
String valueFromEmptyStr = mapper.writeValueAsString(asMap(key, ""));
objectReader.readValue(valueFromEmptyStr);
}
@Test ( expected = MismatchedInputException.class)
public void testStrictDeserializeFromEmptyString() throws Exception {
final String key = "duration";
final ObjectMapper mapper = mapperBuilder()
.withConfigOverride(Duration.class,
o -> o.setFormat(JsonFormat.Value.forLeniency(false)))
.build();
final ObjectReader objectReader = mapper.readerFor(MAP_TYPE_REF);
final String dateValAsNullStr = null;
// even with strict, null value should be deserialized without throwing an exception
String valueFromNullStr = mapper.writeValueAsString(asMap(key, dateValAsNullStr));
Map<String, Duration> actualMapFromNullStr = objectReader.readValue(valueFromNullStr);
assertNull(actualMapFromNullStr.get(key));
String dateValAsEmptyStr = "";
String valueFromEmptyStr = mapper.writeValueAsString(asMap(key, dateValAsEmptyStr));
objectReader.readValue(valueFromEmptyStr);
}
@Test
public void testDeserializationCaseInsensitiveEnabledOnValue() throws Throwable
{
final ObjectMapper mapper = newMapperBuilder()
.withConfigOverride(LocalDateTime.class, o -> o.setFormat(JsonFormat.Value
.forPattern("dd-MMM-yyyy HH:mm")
.withFeature(Feature.ACCEPT_CASE_INSENSITIVE_VALUES)))
.build();
ObjectReader reader = mapper.readerFor(LocalDateTime.class);
String[] jsons = new String[] {"'01-Jan-2000 13:14'","'01-JAN-2000 13:14'", "'01-jan-2000 13:14'"};
for(String json : jsons) {
expectSuccess(reader, LocalDateTime.of(2000, Month.JANUARY, 1, 13, 14), json);
}
}
@Override
public JsonSerializer<?> findReferenceSerializer(SerializationConfig config,
ReferenceType refType, BeanDescription beanDesc, JsonFormat.Value formatOverrides,
TypeSerializer contentTypeSerializer, JsonSerializer<Object> contentValueSerializer)
{
final Class<?> raw = refType.getRawClass();
if (Optional.class.isAssignableFrom(raw)) {
boolean staticTyping = (contentTypeSerializer == null)
&& config.isEnabled(MapperFeature.USE_STATIC_TYPING);
return new GuavaOptionalSerializer(refType, staticTyping,
contentTypeSerializer, contentValueSerializer);
}
return null;
}
/**
* Contextualization is needed to see whether we can "inline" deserialization
* of String values, or if we have to use separate value deserializer.
*/
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanProperty property)
throws JsonMappingException
{
JsonDeserializer<?> deser = _elementDeserializer;
// May have a content converter
deser = findConvertingContentDeserializer(ctxt, property, deser);
JavaType type = ctxt.constructType(String.class);
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(type, property);
} else { // if directly assigned, probably not yet contextual, so:
deser = ctxt.handleSecondaryContextualization(deser, property, type);
}
// One more thing: allow unwrapping?
Boolean unwrapSingle = findFormatFeature(ctxt, property, String[].class,
JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
NullValueProvider nuller = findContentNullProvider(ctxt, property, deser);
// Ok ok: if all we got is the default String deserializer, can just forget about it
if ((deser != null) && isDefaultDeserializer(deser)) {
deser = null;
}
if ((_elementDeserializer == deser)
&& (_unwrapSingle == unwrapSingle)
&& (_nullProvider == nuller)) {
return this;
}
return new StringArrayDeserializer(deser, nuller, unwrapSingle);
}
private static Map<Class<?>, JsonFormat.Shape> resolveShapeConfigOverrides(List<String> overrides, ClassLoader classLoader) {
if (overrides == null) {
return null;
}
final Map<Class<?>, JsonFormat.Shape> resolvedOverrides = new LinkedHashMap<>();
final Map<String, String> overridesMap = Settings.convertToMap(overrides);
for (Map.Entry<String, String> entry : overridesMap.entrySet()) {
final Class<?> cls = Settings.loadClass(classLoader, entry.getKey(), Object.class);
final JsonFormat.Shape shape = JsonFormat.Shape.valueOf(entry.getValue());
resolvedOverrides.put(cls, shape);
}
return resolvedOverrides;
}
@Test
public void testStrictDeserializeFromNumberInt() throws Exception
{
ObjectMapper mapper = newMapperBuilder()
.withConfigOverride(LocalDate.class,
o -> o.setFormat(JsonFormat.Value.forLeniency(false)))
.build();
ShapeWrapper w = mapper.readValue("{\"date\":123}", ShapeWrapper.class);
LocalDate localDate = w.date;
assertEquals("The value is not correct.", LocalDate.of(1970, Month.MAY, 04),
localDate);
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
public Date getNextValidTime()
{
if (StringUtils.isNotEmpty(cronExpression))
{
return CronUtils.getNextExecution(cronExpression);
}
return null;
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
Boolean unwrapSingle = findFormatFeature(ctxt, property, EnumSet.class,
JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
JsonDeserializer<?> deser = _enumDeserializer;
if (deser == null) {
deser = ctxt.findContextualValueDeserializer(_enumType, property);
} else { // if directly assigned, probably not yet contextual, so:
deser = ctxt.handleSecondaryContextualization(deser, property, _enumType);
}
return withResolved(deser, unwrapSingle);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializers,
BeanProperty property) throws JsonMappingException
{
JsonFormat.Value format = findFormatOverrides(serializers,
property, Boolean.class);
if (format != null) {
JsonFormat.Shape shape = format.getShape();
if (shape.isNumeric()) {
return new AsNumber(_forPrimitive);
}
}
return this;
}
@Test
public void testDeserializationCaseInsensitiveEnabled() throws Throwable
{
final ObjectMapper mapper = newMapperBuilder()
.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES, true)
.withConfigOverride(LocalDateTime.class, o -> o.setFormat(
JsonFormat.Value.forPattern("dd-MMM-yyyy HH:mm")))
.build();
ObjectReader reader = mapper.readerFor(LocalDateTime.class);
String[] jsons = new String[] {"'01-Jan-2000 13:45'","'01-JAN-2000 13:45'", "'01-jan-2000 13:45'"};
for(String json : jsons) {
expectSuccess(reader, LocalDateTime.of(2000, Month.JANUARY, 1, 13, 45), json);
}
}
@Test(expected = MismatchedInputException.class)
public void testStrictDeserializeFromString() throws Exception
{
ObjectMapper mapper = newMapperBuilder()
.withConfigOverride(LocalDate.class,
o -> o.setFormat(JsonFormat.Value.forLeniency(false)))
.build();
mapper.readValue("{\"value\":123}", Wrapper.class);
}
/**
* 充币/提币总量统计
*
* @param type ["WITHDRAW" "RECHARGE"]
* @return
*/
@PostMapping("recharge-or-withdraw-amount")
@AccessLog(module = AdminModule.FINANCE, operation = "充币/提币总量统计")
public MessageResult recharge(TransactionTypeEnum type
, @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") Date startDate
, @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") Date endDate
) {
Assert.isTrue(type == TransactionTypeEnum.WITHDRAW || type == TransactionTypeEnum.RECHARGE, "type只能为 5(充币) 或 6(提币)");
if (endDate == null) {
endDate = DateUtil.getDate(new Date(), 1);
}
Assert.notNull(startDate, "startDate must not be null");
ProjectionOperation projectionOperation = Aggregation.project("date", "year", "month", "day", "type", "unit", "amount", "fee").andExclude("_id");
MatchOperation matchOperation = Aggregation.match(
Criteria.where("type").is(type.toString())
.andOperator(Criteria.where("date").gte(startDate), Criteria.where("date").lte(endDate))
);
GroupOperation groupOperation = Aggregation.group("type", "unit").sum("amount").as("amount").sum("fee").as("fee");
Aggregation aggregation = Aggregation.newAggregation(projectionOperation, matchOperation, groupOperation);
AggregationResults<TurnoverStatisticsVO> aggregationResults = this.mongoTemplate.aggregate(aggregation, "turnover_statistics", TurnoverStatisticsVO.class);
List<TurnoverStatisticsVO> list = aggregationResults.getMappedResults();
logger.info("{}总额:{}", type == TransactionTypeEnum.WITHDRAW ? "提币" : "充币", list);
return MessageResult.getSuccessInstance(messageSource.getMessage("SUCCESS"), list);
}
@Override
protected JSR310FormattedSerializerBase<?> withFormat(DateTimeFormatter formatter,
Boolean useTimestamp,
JsonFormat.Shape shape)
{
return new ZonedDateTimeSerializer(this, formatter,
useTimestamp, _useNanoseconds, _writeZoneId);
}
private boolean acceptCaseInsensitiveValues(DeserializationContext ctxt, JsonFormat.Value format)
{
Boolean enabled = format.getFeature( Feature.ACCEPT_CASE_INSENSITIVE_VALUES);
if( enabled == null) {
enabled = ctxt.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_VALUES);
}
return enabled;
}
private void assertDateFormatAnnotation(JFieldVar field, String expectedPattern) throws Exception {
assertEquals(1, field.annotations().size());
Optional<JAnnotationUse> optionalAnnotation = field.annotations().stream().findFirst();
if (optionalAnnotation.isPresent() && JsonFormat.class.getName().equals(optionalAnnotation.get().getAnnotationClass().fullName())) {
assertPatternValue(optionalAnnotation.get(), expectedPattern);
} else {
fail();
}
}
@Override
public void setCell(Date o, Cell cell, Field field) {
if (o != null) {
String format = field.getAnnotation(JsonFormat.class).pattern();
cell.setCellValue(new SimpleDateFormat(format).format(o));
}
}
public void testShapeViaDefaults() throws Exception
{
assertEquals(aposToQuotes("{'b':true}"),
MAPPER.writeValueAsString(new BooleanWrapper(true)));
ObjectMapper m = afterburnerMapperBuilder()
.withConfigOverride(Boolean.class,
o -> o.setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.NUMBER)))
.build();
assertEquals(aposToQuotes("{'b':1}"),
m.writeValueAsString(new BooleanWrapper(true)));
}
private MethodSpec buildParametersMethod(){
JsonFormat jsonFormat = field.getAnnotation(JsonFormat.class);
return MethodSpec.methodBuilder("newParameters")
.addModifiers(Modifier.PROTECTED)
.addAnnotation(Override.class)
.returns(JsonDeserializerParameters.class)
.addStatement("return $T.get()\n\t\t.newDeserializerParameters()\n\t\t.setPattern($S)\n\t\t.setShape($T.$L)"
,TypeName.get(JacksonContextProvider.class)
,jsonFormat.pattern()
,TypeName.get(JsonFormat.Shape.class)
,jsonFormat.shape().toString())
.build();
}
@Override
public JsonFormat.Value findFormat(Annotated ann) {
JsonFormat.Value v1 = _primary.findFormat(ann);
JsonFormat.Value v2 = _secondary.findFormat(ann);
if (v2 == null) { // shouldn't occur but just in case
return v1;
}
return v2.withOverrides(v1);
}
@Override // since 2.9
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property) throws JsonMappingException
{
Boolean caseInsensitive = findFormatFeature(ctxt, property, handledType(),
JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
if (caseInsensitive == null) {
caseInsensitive = _caseInsensitive;
}
return withResolved(caseInsensitive);
}
/**
* Convenience method that uses {@link #findFormatOverrides} to find possible
* defaults and/of overrides, and then calls <code>JsonFormat.Value.getFeature(...)</code>
* to find whether that feature has been specifically marked as enabled or disabled.
*
* @param typeForDefaults Type (erased) used for finding default format settings, if any
*
* @since 2.7
*/
protected Boolean findFormatFeature(SerializerProvider provider,
BeanProperty prop, Class<?> typeForDefaults, JsonFormat.Feature feat)
{
JsonFormat.Value format = findFormatOverrides(provider, prop, typeForDefaults);
if (format != null) {
return format.getFeature(feat);
}
return null;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+08:00")
public Date getActDate() {
return actDate;
}
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
public Date getCreateTime() {
return createTime;
}