首页 > 解决方案 > Json 在 postgres DB 中存储为 = 而不是 : 冒号

问题描述

我有一个 Gradle spring-boot 项目。我想在 postgres DB 列(规则)中存储一个 json,因此将列的类型定义为 TEXT。当我通过邮递员点击保存端点时,我正在发送此数据

{
  "rules": {"key": "97773e0b-3639-4af5-9585-93bc176715c0", "fieldName": "esn", "operator": "eq", "operands": ["599320"]},
  "name": "user",
  "sso": "502622018",
  "ruleMatching": "ALL"
}

但是当我点击 GET 端点时,我得到的响应不是 json,而是一种字符串,其中 : 转换为 = 并且不存储引号。

{
    "id": 9,
    "name": "user",
    "ruleMatching": "ALL",
    "sso": "502622018",
    "rules": "{key=97773e0b-3639-4af5-9585-93bc176715c0, fieldName=esn, operator=eq, operands=[599320]}"
}

如何将rulesDB 中的正确 json 保存为 TEXT 类型?有什么建议吗?

这是Entity定义和dto定义

@SuppressWarnings("serial")
@Entity
@Getter @Setter @AllArgsConstructor @NoArgsConstructor
@Builder(toBuilder=true)
@Table(name="saved_filters")
@TypeDef(
        name = "jsonb",
        typeClass = JsonBinaryType.class
    )
public class SavedFilter implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private int id;

    @Column(name="name")
    private String name;

  
    @Column(name="rule_matching")
    private String ruleMatching;
    
    
    @Column(name="rules", columnDefinition= "TEXT")
    private String rules;

    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_sso")
    private User user;

----DTO--

@SuppressWarnings("serial")
@Data
@Getter @Setter @AllArgsConstructor @NoArgsConstructor
@Builder(toBuilder=true)
public class SavedFilterDto implements Serializable {

    private int id;

    private String name;
    
    @JsonProperty("rules")
    private Object rules;
    
    private String ruleMatching;

    private String sso;      
    
}

将列更改为 jsonb 后,出现以下错误

RemoteUserContext --> ef227333-4629-4571-bf2f-210c64902eea
2021-03-23 23:42:23 [http-nio-9090-exec-1] DEBUG c.g.d.o.m.c.FilterController.createSavedFilter - Start...SavedFilterDto(id=0, name=user, rules={key=97773e0b-3639-4af5-9585-93bc176715c0, fieldName=esn, operator=eq, operands=[599320]}, ruleMatching=ALL, sso=502622018)
Hibernate: select user0_.sso as sso1_35_0_, user0_.email as email2_35_0_, user0_.first_name as first_na3_35_0_, user0_.hidden as hidden4_35_0_, user0_.last_name as last_nam5_35_0_, user0_.updated_at as updated_6_35_0_, user0_.user_id as user_id7_35_0_ from user_info user0_ where user0_.sso=?
Hibernate: insert into saved_filters (name, rule_matching, rules, user_sso) values (?, ?, ?, ?)
2021-03-23 23:42:24 [http-nio-9090-exec-1] ERROR c.g.d.o.m.e.GenericExceptionHandler.handleException - Application error
org.springframework.orm.jpa.JpaSystemException: java.lang.IllegalArgumentException: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('k' (code 107)): was expecting double-quote to start field name
 at [Source: (String)"{key=97773e0b-3639-4af5-9585-93bc176715c0, fieldName=esn, operator=eq, operands=[599320]}"; line: 1, column: 3]; nested exception is org.hibernate.HibernateException: java.lang.IllegalArgumentException: com.fasterxml.jackson.core.JsonParseException: Unexpected character ('k' (code 107)): was expecting double-quote to start field name
 at [Source: (String)"{key=97773e0b-3639-4af5-9585-93bc176715c0, fieldName=esn, operator=eq, operands=[599320]}"; line: 1, column: 3]
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:351) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:253) ~[spring-orm-5.1.6.RELEASE.jar:5.1.6.RELEASE]

如果我更改私有对象规则;在 DTO 到私有字符串规则;..我收到以下错误:

2021-03-24 11:12:05 [http-nio-9090-exec-10] WARN  o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver.logException - Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of START_OBJECT token
 at [Source: (PushbackInputStream); line: 2, column: 12] (through reference chain: com.ge.digital.oa.moa.dto.SavedFilterDto["rules"])]

标签: javajsonspringpostgresqlhibernate

解决方案


更新的答案

如果以 json 格式保存不是您最关心的问题,那么您可以遵循这个答案。

您只需做一件事即可轻松实现。将您的密钥字符串与关联实体转换为一个类并使其嵌入:

{"key": "97773e0b-3639-4af5-9585-93bc176715c0", "fieldName": "esn", "operator": "eq", "operands": ["599320"]}.

创建可嵌入类:

@Embeddable
Public class Rules
{
 private String key;
private String fieldName;
private String operator;
private String eq;
List<String> operands;
//getters and setters
}

现在在您的SaveFilter班级中,添加带有嵌入注释的规则实体:

 @Embedded
 @Column(name="rules")
 private Rules rules;

这会将您的完整对象保存为嵌入对象的每个实体的不同列。


推荐阅读