SpringBoot and MongoDB Saving Issue for a JSONObject Field inside a POJO

Viewed 983

I have a simple POJO similar to below. Getters and setters are omitted for brevity.

@Document(collection = "posts")
public class Post {
    @Id
    public String id;
    
    @Field(name = "author")
    public String author;
    
    @Field(name = "title")
    public String title;
    
    @Field(name = "body")
    public JSONObject body;
    
    public Post() {

    }
    
    public Post(String id, String author, String title, JSONObject body) {
        this.id = id;
        this.title = title;
        this.author = author;
        this.body = body;
    }

And I use default save from MongoRepository in order to save my data:

import org.springframework.data.mongodb.repository.MongoRepository;

public interface PostRepository extends MongoRepository<Post, String> {

}

It is getting saved to MongoDB by using the codes below:

@PostMapping
    public Post addPost(HttpEntity<String> httpEntity) {
        try {
            JSONObject obj = new JSONObject(httpEntity.getBody());

            Post p1 = new Post("123", obj.getString("author"), obj.getString("title"), 
                    obj.getJSONObject("body"));

            return postRepository.save(p1);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Foo Not Found", e);
        }
    }

When it is saved in MongoDB, it stores fields that are not originally in the JSON that I am supposed to save.

Original JSON:

{
   body: {
     blocks: {
        [
           { data: "Data 1", type: "Type 1" },
           { data: "Data 2", type: "Type 2" },
        ]
     },
     version: "1.2.2"
   }
}

Saved JSON:

{
   body: {
     map: {
        blocks: {
           myArrayList:
           [
               { map: { data: "Data 1", type: "Type 1" }, _class: "org.json.JSONObject" },
               { map: { data: "Data 2", type: "Type 2" }, _class: "org.json.JSONObject" },
           ],
           _class: "org.json.JSONArray"
        },
        version: "1.2.2"
     }
   }
}

When I try to get the data, I am receiving the following error:

java.lang.IllegalStateException: Cannot set property map because no setter, no wither and it's not part of the persistence constructor public org.json.JSONObject()!

This is how I get the data:

@GetMapping(path = "/{id}")
    public Post getPost(@PathVariable String id) {
        try {
            Optional<Post> post = postRepository.findById(id);

            return post.orElseThrow();
        } catch (Exception e) {
            e.printStackTrace();
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Foo Not Found", e);
        }
    }

My first question is, is there a way to save a JSON object to MongoDB without the extra fields (e.g. map, myArrayList)?

Second, how am I supposed to retrieve data with a JSONObject field in the POJO?

Thanks in advance!

1 Answers

Here is a generic solution to store any document

package io.innoit.elearning.generic;

import java.util.List;

import org.bson.Document;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/generic")
@CrossOrigin(origins = { "*" })
public class GenericController {

    @Autowired
    private MongoTemplate mongoTemplate;

    @PostMapping
    public ResponseEntity<Document> addData(@RequestBody String data) {
        JSONObject jsonObject = new JSONObject(data);
        String documentName = jsonObject.getString("documentName");
        Document doc = Document.parse(data);
        Document insertedDoc = mongoTemplate.insert(doc, documentName);
        return new ResponseEntity<>(insertedDoc, HttpStatus.CREATED);

    }

    @GetMapping("/{documentName}")
    public List<Document> getData(@PathVariable String documentName) {
        List<Document> allData = mongoTemplate.findAll(Document.class, documentName);
        return allData;
    }

}
Related