Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When json is deserialized, the JsonDeserializer returned in the custom ContextualDeserializer is not executed. #2978

Open
LkZtCode opened this issue Aug 26, 2024 · 2 comments
Assignees
Labels
status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged

Comments

@LkZtCode
Copy link

this is my custom ContextualDeserializer
image

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Aug 26, 2024
@christophstrobl
Copy link
Member

If you'd like us to spend some time investigating, please take the time to provide a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem.

@christophstrobl christophstrobl added the status: waiting-for-feedback We need additional information before we can continue label Aug 26, 2024
@LkZtCode
Copy link
Author

this my custom @interface

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.trustasia.cloudpki.common.base.core.localizedtime.jsonformat.deserialize.LocalizedJsonFormatDeserialize;
import com.trustasia.cloudpki.common.base.core.localizedtime.jsonformat.serialize.LocalizedJsonFormatSerialize;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = LocalizedJsonFormatSerialize.class)
@JsonDeserialize(using = LocalizedJsonFormatDeserialize.class)
public @interface LocalizedJsonFormat {

    String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";

    String pattern() default DEFAULT_PATTERN;
}

this is custom JsonDeserializer

@Slf4j
public class LocalizedDateDeserialize extends JsonDeserializer<Date> {
    private String pattern;

    private ZoneId defaultZoneid = ZoneId.systemDefault();
    private SimpleDateFormat defaultSimpleDateFormat;

    private CommonSecurity commonSecurity;

    public LocalizedDateDeserialize(String pattern) {
        this.pattern = pattern;
        this.defaultSimpleDateFormat = new SimpleDateFormat(pattern);
        this.commonSecurity = SpringUtils.getBean(CommonSecurity.class);
    }

    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
        String dateStr = jsonParser.getText().trim();
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        // 尝试获取时区ID,若无则使用默认处理逻辑
        ZoneId targetZoneId = commonSecurity.getCurrentTimeZoneId()
                .or(() -> Optional.of(defaultZoneid.getId()))
                .map(ZoneId::of)
                .orElseGet(() -> defaultZoneid);

        if (defaultZoneid.equals(targetZoneId)) {
            return generateDefaultDate(dateStr);
        }

        EnhanceSimpleDateFormat enhanceSimpleDateFormat = new EnhanceSimpleDateFormat(this.pattern, targetZoneId);
        try {
            return enhanceSimpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.error("LocalizedDateDeserialize parse Date error", e);
            throw new LocalizedJsonFormatException(String.format("Failed to parse Date value '%s'", dateStr));
        }
    }

    private Date generateDefaultDate(String dateStr) {
        try {
            return defaultSimpleDateFormat.parse(dateStr);
        } catch (ParseException e) {
            log.error("LocalizedDateDeserialize parse Date error", e);
            throw new LocalizedJsonFormatException(String.format("Failed to parse Date value '%s'", dateStr));
        }
    }
}
@NoArgsConstructor
@Slf4j
public class LocalizedJsonFormatDeserialize extends JsonDeserializer<Object> implements ContextualDeserializer {

    @Override
    public Object deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException, JacksonException {
        throw new LocalizedJsonFormatException("this is proxy deserializer,not support deserialize");
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), Date.class)) {
                LocalizedJsonFormat localizedJsonFormat = beanProperty.getAnnotation(LocalizedJsonFormat.class);
                if (localizedJsonFormat == null) {
                    localizedJsonFormat = beanProperty.getContextAnnotation(LocalizedJsonFormat.class);
                }
                if (localizedJsonFormat != null) {
                    return new LocalizedDateDeserialize(localizedJsonFormat.pattern());
                }
            }
            return deserializationContext.findContextualValueDeserializer(beanProperty.getType(), beanProperty);
        }
        return deserializationContext.findNonContextualValueDeserializer(null);
    }
}

in entity used @LocalizedJsonFormat

@Getter
@Setter
public class OpenApiBaseDomain implements Serializable {
    public Long id;
    /**
     * 创建时间
     */
    @LocalizedJsonFormat
    private Date createAt;
    /**
     * 更新时间
     */
    @LocalizedJsonFormat
    private Date updateAt;
    private Boolean deleted;
    /**
     * 版本号
     */
    private Long version;
}

In the mvc framework, @LocalizedJsonFormat will follow custom logic, but in redis deserialization, @LocalizedJsonFor will not follow custom logic.

I added the relevant logic of custom annotations to the createContextual of DateBasedDeserializer. Redis will use the custom logic when serializing.

image

So I think that the logic of custom JsonDeserializer is implemented during the deserialization calling process of redis.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

3 participants