8

The API below accept a json string from client, and the map it into a Email object. How can I get request body (email) as a raw String? (I want both raw-string and typed version of email parameter)

PS: This question is NOT a duplicate of: How to access plain json body in Spring rest controller?

@PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(@RequestBody Email email) {
    //...
    return new ResponseEntity<>(HttpStatus.OK);
}
code đờ
  • 554
  • 1
  • 9
  • 19
  • have you tried using the toString or StringBuilder method? – kalpaj agrawalla Aug 24 '20 at 03:35
  • Why, _exactly_, is it not a duplicate? – chrylis -cautiouslyoptimistic- Aug 24 '20 at 03:38
  • 1
    @chrylis-cautiouslyoptimistic- The other question is about getting ONLY a raw String, not caring about typed (mapped) version of the parameter – code đờ Aug 24 '20 at 03:40
  • @kalpajagrawalla I think it will cause some overhead, since we have to convert the object back to a JSON String – code đờ Aug 24 '20 at 03:42
  • And did you try just putting both? – chrylis -cautiouslyoptimistic- Aug 24 '20 at 03:56
  • Just put both a `String` and typed object in there with `@RequestBody`. What you duped as not a duplicate is actually a duplicate as that is the way to obtain the raw payload. However, I would suggest that if you need both, you are doing something wrong with your typed object. – M. Deinum Aug 24 '20 at 06:21
  • 1
    This is neither a duplicate (the specific requirement is to get both the parsed model and the raw HTTP body), nor it is a dubious use case.I can give you a concrete example where this would be highly useful: I want to use Bean Validation on the parsed model, and I need to pass on the raw body (JSON) to another downstream consumer, e.g. an Azure Event Hub, the Java library for which accepts (among others) a raw string (JSON) as input. – Hein Blöd Mar 17 '23 at 09:44
  • By the way, when trying to passing both `@RequestBody Model` and `HttpEntity` as arguments, depending on the order of the arguments either the body of the `HttpEntity` is `null` or the model gets parsed as if there was no body. I guess that is because the InputStream gets consumed only once and is therefore not available for the other argument. – Hein Blöd Mar 17 '23 at 09:47

4 Answers4

6

You can do it in more than one way, listing two

 1. **Taking string as the paramater**,
     @PostMapping(value = "/mailsender")
        public ResponseEntity<Void> sendMail(@RequestBody String email) {
            //... the email is the string can be converted to Json using new JSONObject(email) or using jackson.
            return new ResponseEntity<>(HttpStatus.OK);
        }

 2. **Using Jackson** 
         @PostMapping(value = "/mailsender")
            public ResponseEntity<Void> sendMail(@RequestBody Email email) {
                //...
                ObjectMapper mapper = new ObjectMapper(); 
                String email = mapper.writeValueAsString(email); //this is in string now
                return new ResponseEntity<>(HttpStatus.OK);
            }
  • 1
    The first way is the solution I'm using right now, but I wish Spring provide a better way to solve this problem. – code đờ Aug 25 '20 at 04:01
  • the first one: email is a encoded form string, which is modified by spring – Yin Mar 31 '21 at 14:57
0

Spring uses Jackson for this in the back, you could use it to serialize it to an string. Like so:

@Autowired private ObjectMapper jacksonMapper;

@PostMapping(value = "/mailsender")
public ResponseEntity<Void> sendMail(@RequestBody Email email) {
    //...
    log.info("Object as String: " + jacksonMapper.writeValueAsString(email));
    return new ResponseEntity<>(HttpStatus.OK);
}
Chris
  • 109
  • 2
  • 9
0

I did not get all things about this question, but I try to answer as I understand. Well, if you want to get request body:

  • as you say How to access plain json body in Spring rest controller? here already writen how to do this. If something wrong, maybe you send wrong json or not suitable type as you wite inside Email class. Maybe your request comes url filter

  • second way try like this:

    private final ObjectMapper mapper = new ObjectMapper();
    
    @PostMapping(value = "/mailsender")
    public ResponseEntity<Void> sendMail(HttpServletRequest req) {
        // read request body
        InputStream body = req.getInputStream();        
        byte[] result = ByteStreams.toByteArray(body);
        String text =new String(result,"UTF-8");
        //convert to object
        Email email = mapper.readValue(body, Email .class);
        return new ResponseEntity<>(HttpStatus.OK);
    }
    
    

If you want to convert object to json string read this post

Ulug'bek
  • 2,762
  • 6
  • 31
  • 59
-1

you can create json of type string using GSON library

Gson gson = new Gson();

@PostMapping(value = "/endpoint")
public ResponseEntity<Void> actionController(@RequestBody Car car) {
    //...
    log.info("Object as String: " + this.gson.toJson(car));
    return new ResponseEntity<>(HttpStatus.OK);
}