Reputation: 165
How can I save Raw Json as String in the MsSql db with the POST request - using Jackson ObjectMapper to convert the string to Json but not able to change raw json into string?
{
"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"
}
How can I save this save json as integer, varchar, string, string, date column in the db? 1,someName, "{"title": "example glossary","GlossDiv": {"title": "S","GlossTerm": "Standard Generalized Markup Language"}","{"name":"someone","age": 121}", 03-11-2019.00:00:00.
** Update ** For simplicity here is the simple json
{
"id":1,
"jsonObjectHolder":{
"name": "Name",
"age" : 404
}}
Controller:
@PostMapping("/postJson")
public void postJson(@RequestBody TryJson tryJson) {
tryJsonService.postJson(tryJson);
}
Service:
public void postJson(TryJson tryJson) {
tryJsonRepository.save(tryJson);
}
Repo:
public interface TryJsonRepository extends CrudRepository<TryJson, Integer> {
}
Model:
@Entity
@Table(name = "TryJson") public class 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 null
Not sure what I am missing here. I do get jsonObjectHolder populated during the debugging but then still I get NULL TryJson [Id=1, JsonColumn=null, jsonObjectHolder={"name":"Name","age":404}]
Update 2
I am getting null pointer exception.
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]
Here is my new model
@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);
}
}
Upvotes: 1
Views: 17240
Reputation: 350
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());
}
Upvotes: 0
Reputation: 2040
You could define a JsonNode
json property to hold the part you want to persist as text, then mark it as @Transient so JPA does not try to store it on database. However, jackson should be able to translate it back and forward to Json.
Then you can code getter/setter for JPA, so you translate from JsonNode to String back and forward. You define a getter getJsonString that translate JsonNode json to String. That one can be mapped to a table column, like 'json_string', then you define a setter where you receive the String from JPA and parse it to JsonNode that will be avaialable for jackson.
Do not forget to add @JsonIgnore to getJsonString so Jackson does not try to translate to json as 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();
}
}
}
UPDATE:
If you mark jsonColumn with @Column spring will use reflection to pull out the data with default initialization null
, getJsonColumn
translation will never be executed:
@JsonIgnore
@Column(name = "json_column")
private String jsonColumn;
You do not need a jsonColumn, just make sure you mark your setters with @Column
, so spring uses gettets/setters to persist to database, when persisting, jpa will execute getJsonColumn
, when reading, jpa will execute setJsonColumn
and jsonNode will be translated back and forward to string:
@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);
}
}
Upvotes: 3