java - Tapestry JPA Jackson 反序列化

标签 java json hibernate jackson tapestry

我正在开发一个最初不是我创建的项目,其中数据存储在内存中。我目前正在将这些数据移入数据库。我正在使用 hibernate 和 Tapestry JPA 来完成此操作。在项目中的某个时刻,通过 @JsonDeserialize 使用了 Jackson 反序列化(实际上与 UI 相关,但我怀疑这是否相关)。注释,带有反序列化器类(我们称之为 DefinitionDeserializer )。 DefinitionDeserializer然后创建数据库表 ( Definition ) 的 POJO 表示形式的实例(我们称之为 D_DEFINITION )。然而,D_DEFINITION与另一个表 ( D_TYPE ) 有连接(因此还有另一个 POJO ( PeriodType ))。为了解决此连接,我使用 Tapestry 服务 ( ConnectingService ),我通常通过 @Inject 注入(inject)该服务注解。但是,当对象(我试图在其中注入(inject)服务,即 DefinitionDeserializer )是通过 new 创建时,我无法使用这种注入(inject)方法。关键字 - @JsonDeserialize 似乎就是这种情况注解。我也无法使用ConnectingService无需通过 @Inject 注入(inject)它关键字,因为那时我无法在 ConnectingService 中注入(inject)任何其他服务要么,我目前正在做。

我希望这个描述不会让您感到太困惑,我无法与您分享实际的代码,而且我认为一个最小的示例不会更好,因为这是一个非常复杂的情况,并且不会'不会是这么小的一段代码。不过,如果您需要一个,我可以尝试提供一个。

基本上我需要的是一种方法来告诉 JsonDeserialize采用 Tapestry 服务而不是创建 DefinitionDeserializer 的实例本身。

编辑:作为示例的类:

public DefinitionDeserializer extends StdDeserializer<Definition> {
    private static final long serialVersionUID = 1L;
    //TODO: The injection doesn't work yet
    @Inject
    private ConnectingService connectingService;

    public DefinitionDeserializer() {
        this(null);
    }

    public DefinitionDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Definition deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Definition pd = new Definition();
        JsonNode node = p.getCodec().readTree(p);
        if (node.has("type"))
            pd.setType(periodTypeDao.findByValue("PeriodType." + node.get("type").asText()));

        return pd;
    }

}
<小时/>
@Entity
@Table(name = Definition.TABLE_NAME)
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region =
        JpaEntityModelConstants.CACHE_REGION_ADMINISTRATION)
public class Definition {

    public static final String TABLE_NAME = "D_DEFINITION";
    private static final long serialVersionUID = 389511526676381027L;

    @Id
    @SequenceGenerator(name = JpaEntityModelConstants.SEQUENCE_NAME, sequenceName = JpaEntityModelConstants.SEQUENCE_NAME, initialValue = 1, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = JpaEntityModelConstants.SEQUENCE_NAME)
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumns({
            @JoinColumn(name = "FK_TYPE", referencedColumnName = "ID")}
    )
    private PeriodType type;


    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public PeriodType getType() {
        return type;
    }

    public void setType(PeriodType dpmType) {
        this.type = dpmType;
    }

    //More columns
}
<小时/>

PeriodType看起来与 Definition 几乎相同.

<小时/>
//BaseService contains all the standard methods for tapestry JPA services
public interface ConnectingService extends BaseService<PeriodType> {

}
<小时/>
public class ConnectingServiceImpl extends BaseServiceImpl<PeriodType> implements ConnectingService {

    public ConnectingServiceImpl() {
        super (PeriodType.class);
    }
}
<小时/>

目前我正在这样使用它(这不起作用):

@JsonDeserialize(using = DefinitionDeserializer.class)
@JsonSerialize(using = DefinitionSerializer.class)
private Definition definition;

最佳答案

@JsonDeserialize 不会创建反序列化器的实例,它只是提示 ObjectMapper 了解反序列化时使用哪个类。

默认情况下,ObjectMapper 使用 Class.newInstance() 实例化反序列化器,但您可以指定自定义 HandlerInstantiator (ObjectMapper#setHandlerInstantiator())其中您可以使用 Tapestry 的 ObjectLocator 来获取反序列化器的实例,即使用 ObjectLocator#autobuild(),或者使用 ObjectLocator#getService() if您的反序列化器本身就是 Tapestry 服务。

更新:

public class MyHandlerInstantiator extends HandlerInstantiator
{
    private final ObjectLocator objectLocator;

    public MyHandlerInstantiator(ObjectLocator objectLocator)
    {
        this.objectLocator = objectLocator;
    }

    @Override
    public JsonDeserializer<?> deserializerInstance(
     DeserializationConfig config, Annotated annotated, Class<?> deserClass)
    {
        // If null returned here instance will be created via reflection
        // you can always use objectLocator, or use it conditionally
        // just for some classes
        return objectLocator.autobuild(deserClass);
    }

    // Other method overrides can return null
}

然后当您配置ObjectMapper时,使用ObjectLocator@Inject实例来创建自定义HandlerInstantiator<的实例,即:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setHandlerInstantiator(new MyHandlerInstantiator(objectLocator));
return objectMapper;

关于java - Tapestry JPA Jackson 反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53560888/

相关文章:

javascript - JavaScript 中的数组和对象处理用于获取 highchart json 数据

php - 解析 JSON 时定位同一标签的特定实例

java - JPA/Hibernate - x 实例的标识符被更改异常

java - 通过 hibernate 获取不同的值

java - 如何使用 XmlPullParser 解析复杂的 XML

java - 工具提示文本根据鼠标悬停在文本框中的单词而变化?

java - 使用常量或系统属性

java - 如何让 BlazeDS 忽略属性?

java - 返回未知类型 Java

java - CascadeType.ALL 不更新子元素