java - 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]}"
}
如何将rules
DB 中的正确 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"])]
解决方案
更新的答案
如果以 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;
这会将您的完整对象保存为嵌入对象的每个实体的不同列。
推荐阅读
- c++ - c++ 关于包定价的循环语句
- python - 如何对 Pandas 中多个列的所有分类变量的总和求和
- asp.net-core-mvc - 如何扩展 DataAnnotation 属性并进行客户端验证?
- android - Downloading an image from Cloud Firestore directly into an imageView using FirebaseUI
- javascript - POST 请求 - 字符串参数不存在
- java - 如何在从 Java 代码生成的 Swagger 规范中创建可重用的枚举?
- php - 为什么在“docker logs”中我无法从独白中获取我的日志?
- javascript - React:在现有状态转换期间无法更新(例如在 `render` 中)。渲染方法应该是 props 和 state 的纯函数
- python - 如何修复“无法从'pdfminer.pdfinterp'导入名称'process_pdf'”错误
- javascript - 当我为不同的条件放置不同的 if 语句时,为什么只有一个 if 语句输出?