【问题标题】:Save Raw JSON as string in the database将原始 JSON 保存为数据库中的字符串
【发布时间】:2023-03-18 02:25:02
【问题描述】:

如何使用 POST 请求将原始 Json 保存为 MsSql 数据库中的字符串 - 使用 Jackson ObjectMapper 将字符串转换为 Json 但无法将原始 json 更改为字符串?

{
     "id": 1,
     "someName":"someName",
     "json": {
         "title": "example glossary",
         "GlossDiv": {
             "title": "S",
             "GlossTerm": "Standard Generalized Markup Language"
         }
},
     "anotherjson":{
          "name":"someone",
          "age": 121
},
     "somedate":"03-11-2019.00:00:00" 
}

如何将此保存的 json 保存为数据库中的整数、varchar、字符串、字符串、日期列? 1,someName, "{"title": "示例词汇表","GlossDiv": {"title": "S","GlossTerm": "标准通用标记语言"}","{"name":"someone" "年龄": 121}", 03-11-2019.00:00:00.

** 更新 ** 为简单起见,这里是简单的 json

{
"id":1,
"jsonObjectHolder":{
        "name": "Name",
        "age" : 404
        }}

控制器:

@PostMapping("/postJson")
public void postJson(@RequestBody TryJson tryJson) {
    tryJsonService.postJson(tryJson);
}

服务:

public void postJson(TryJson tryJson) {
    tryJsonRepository.save(tryJson);
}

回购:

public interface TryJsonRepository extends CrudRepository<TryJson, Integer> {

}

型号:

@Entity

@Table(name = "TryJson") 公共类 TryJson {

@Id
@Column(name = "id")
private Integer id;

@JsonIgnore
@Column(name = "json_column")
private String jsonColumn;

@Transient
private JsonNode jsonObjectHolder;

public TryJson() {
}

public TryJson(Integer id, String jsonColumn) {
    this.id = id;
    this.jsonColumn = jsonColumn;
}

public Integer getId() {
    return id;
}

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

public JsonNode getJsonObjectHolder() {
    return jsonObjectHolder;
}

public void setJsonObjectHolder(JsonNode jsonObjectHolder) {
    this.jsonObjectHolder = jsonObjectHolder;
}

public String getJsonColumn() {
    return this.jsonObjectHolder.toString();
}

public void setJsonColumn(String jsonColumn) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    this.jsonObjectHolder = mapper.readTree(jsonColumn);
}

@Override
public String toString() {
    return String.format("TryJson [Id=%s, JsonColumn=%s, jsonObjectHolder=%s]", id, jsonColumn, jsonObjectHolder);
}

}

http://localhost:8080/api/postJson

ID JSON_COLUMN
1个空

不确定我在这里缺少什么。我确实在调试期间填充了 jsonObjectHolder,但我仍然得到 NULL TryJson [Id=1, JsonColumn=null, jsonObjectHolder={"name":"Name","age":404}]

更新 2

我得到空指针异常。

 Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.orm.jpa.JpaSystemException: Exception occurred inside getter of com.example.tryjson.tryjson.model.TryJson.jsonColumn; nested exception is org.hibernate.PropertyAccessException: Exception occurred inside getter of com.example.tryjson.tryjson.model.TryJson.jsonColumn] with root cause 
java.lang.NullPointerException: null
at com.example.tryjson.tryjson.model.TryJson.getJsonColumn(TryJson.java:52) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_192]

这是我的新模型

@Entity
@Table(name = "TryJson")
public class TryJson {
private Integer id;

@Transient
private JsonNode jsonObjectHolder;

public TryJson() {
}

public TryJson(Integer id, JsonNode jsonObjectHolder) {
    this.id = id;
    this.jsonObjectHolder = jsonObjectHolder;
}

@Id
@Column(name = "id")
public Integer getId() {
    return id;
}

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

@Transient
public JsonNode getJsonObjectHolder() {
    return jsonObjectHolder;
}

public void setJsonObjectHolder(JsonNode jsonObjectHolder) {
    this.jsonObjectHolder = jsonObjectHolder;
}

@Column(name = "json_column")
public String getJsonColumn() {
    return this.jsonObjectHolder.toString();
}

public void setJsonColumn(String jsonColumn) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    this.jsonObjectHolder = mapper.readTree(jsonColumn);
}
}

【问题讨论】:

  • 仅供参考,JSON 一个字符串,它是一种基于文本的格式。

标签: json spring-boot spring-data-jpa


【解决方案1】:
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<User>> typeReference = new TypeReference<List<Your_Entity>>() {};
InputStream inputStream = TypeReference.class.getResourceAsStream("/bootstrap.json");
try {
    List<Your_Entity> users = mapper.readValue(inputStream, typeReference);
    log.info("Saving users...");
    userService.saveAllUsers(users);
    log.info(users.size() + " Users Saved...");
} catch (IOException e) {
    log.error("Unable to save users: " + e.getMessage());
}

【讨论】:

    【解决方案2】:

    您可以定义一个JsonNode json 属性来保存您想要作为文本持久化的部分,然后将其标记为@Transient,这样JPA 就不会尝试将其存储在数据库中。但是,jackson 应该能够将它来回转换为 Json。

    然后您可以为 JPA 编写 getter/setter 代码,这样您就可以从 JsonNode 来回转换为 String。您定义了一个将 JsonNode json 转换为 String 的 getter getJsonString。那个可以映射到一个表列,比如'json_string',然后你定义一个setter,你从JPA接收字符串并将其解析为JsonNode,这对jackson可用。

    不要忘记将@JsonIgnore 添加到getJsonString,这样Jackson 就不会尝试将json 转换为jsonString。

    @Entity
    @Table(name = "request")
    public class Request {
    
      private Long id;
    
      private String someName;
    
      @Transient
      private JsonNode json;
    
      @Id
      @GeneratedValue(strategy = GenerationType.AUTO)
      public Long getId() {
        return id;
      }
    
      @Column(name ="someName")
      public String getSomeName() {
        return name;
      }
    
      public void setSomeName(String name) {
        this.name = name;
      }
    
      public void setId(Long id) {
        this.id = id;
      }
    
      // Getter and setter for name
    
      @Transient  // This is for Jackson
      public JsonNode getJson() {
        return json;
      }
    
      public void setJson(JsonNode json) {
        this.json = json;
      }
    
    
      @Column(name ="jsonString")
      public String getJsonString() { // This is for JPA
        return this.json.toString();
      }
    
      public void setJsonString(String jsonString) {  // This is for JPA
        // parse from String to JsonNode object
        ObjectMapper mapper = new ObjectMapper();
        try {
          this.json = mapper.readTree(jsonString);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    

    更新:

    如果你用@Column 标记了jsonColumn,spring 将使用反射来提取默认初始化null 的数据,getJsonColumn 永远不会执行翻译:

    @JsonIgnore
    @Column(name = "json_column")
    private String jsonColumn;
    

    你不需要jsonColumn,只要确保你用@Column标记你的setter,所以spring使用gettets/setters来持久化到数据库,持久化时,jpa会执行getJsonColumn,读取时,jpa会执行@ 987654328@ 和 jsonNode 将被来回转换为字符串:

    @Entity
    @Table(name = "TryJson") public class TryJson {
    
      private Integer id;
    
      @Transient
      private JsonNode jsonObjectHolder;
    
      public TryJson() {
      }
    
      public TryJson(Integer id, String jsonColumn) {
          this.id = id;
          this.jsonObjectHolder = // use mapper to create the jsonObject;
      }
    
      @Id
      @Column(name = "id")
      public Integer getId() {
          return id;
      }
    
      public void setId(Integer id) {
          this.id = id;
      }
    
      public JsonNode getJsonObjectHolder() {
          return jsonObjectHolder;
      }
    
      public void setJsonObjectHolder(JsonNode jsonObjectHolder) {
          this.jsonObjectHolder = jsonObjectHolder;
      }
    
      @Column(name = "json_column")
      public String getJsonColumn() {
          return this.jsonObjectHolder.toString();
      }
    
      public void setJsonColumn(String jsonColumn) throws IOException {
          ObjectMapper mapper = new ObjectMapper();
          this.jsonObjectHolder = mapper.readTree(jsonColumn);
      }
    
      @Override
      public String toString() {
          return String.format("TryJson [Id=%s, JsonColumn=%s, jsonObjectHolder=%s]", id, jsonColumn, jsonObjectHolder);
      }
    }
    

    【讨论】:

    • 谢谢。我得到了获取部分,基本上 jsonNode 对象是从 json 输入创建的,但我不确定我们如何将 json 对象设置为数据库中的字符串。我正在尝试将原始 json 存储为字符串的列获得 NULL 值。
    • @Column(name ="jsonString") public String getJsonString() { // This is for JPA return this.json.toString(); } 这部分是将json转换为字符串,应该在持久化实体时执行。我建议你调试一下,看看转换是否正确。
    • 我更新了我的问题,提供了更多细节。不知道我在这里缺少什么。
    • 请查看我的 cmets
    • 感谢您为我指明了正确的方向。我使用 writevalueasString() 方法而不是 toString 将 jsonNode 对象转换为字符串。为此,我在全局级别实例化了 objectMapper。不能感谢克里斯蒂安解释这个过程。干杯!!
    猜你喜欢
    • 2018-09-21
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-01
    • 2022-08-14
    相关资源
    最近更新 更多