blue-sky
blue-sky

Reputation: 53806

Returning different JSON objects from different requests

I have a writeResponse method within a Spring controller which writes a DTO as Json :

private void writeResponse(String type , Object objectToWrite , ResourceResponse response){
    try {

        MyDTO myDto= new MyDTO ();

        ObjectMapper mapper = new ObjectMapper();
        response.getWriter().write(mapper.writeValueAsString(myDto));

    }
    catch (final JsonGenerationException e) {
        log.error(e.getMessage());
    } catch (final JsonMappingException e) {
        log.error(e.getMessage());
    } catch (final IOException e) {
        log.error(e.getMessage());
    }
}

The method writeResponse is called by multiple methods and each caller method is a different REST endpoint. Currently there is just one DTO type : MyDTO . However more DTO types will be added. To determine which DTO should be written there is a 'type' method parameter. So above method could become :

  private void writeResponse(String type , Object objectToWrite , ResourceResponse response){
            try {

if(type == "1"){
                MyDTO myDto= new MyDTO ();

                ObjectMapper mapper = new ObjectMapper();
                response.getWriter().write(mapper.writeValueAsString(myDto));
}
else if(type == "2")
{
                MyDTO2 myDto2= new MyDTO2 ();

                ObjectMapper mapper = new ObjectMapper();
                response.getWriter().write(mapper.writeValueAsString(myDto2));
}

            }
            catch (final JsonGenerationException e) {
                log.error(e.getMessage());
            } catch (final JsonMappingException e) {
                log.error(e.getMessage());
            } catch (final IOException e) {
                log.error(e.getMessage());
            }
        }

This feels a little clunky. I'm trying to achieve a clean method returning a different JSON depending on which endpoint is called. Is there a better way than what I am suggesting ?

Note : above code is a mix of pseudocode and java.

Upvotes: 0

Views: 218

Answers (2)

spg
spg

Reputation: 9837

You could create an interface:

public interface HasDto {
    Object getDto();
}

A given object class would implement getDto like this:

@Override
public Object getDto() {
    return new Dto1()   
}

And accept a HasDto object in you writeResponse method like this:

private void writeResponse(HasDto hasDto , ResourceResponse response) {
    try {
        ObjectMapper mapper = new ObjectMapper();
        response.getWriter().write(mapper.writeValueAsString(hasDto.getDto()));
    }
    catch (final JsonGenerationException e) {
        log.error(e.getMessage());
    } catch (final JsonMappingException e) {
        log.error(e.getMessage());
    } catch (final IOException e) {
        log.error(e.getMessage());
    }
}

Upvotes: 0

matt forsythe
matt forsythe

Reputation: 3912

Since you have separate URLs each of which are rendering different JSON content, it sounds like the only code in common here is

ObjectMapper mapper = new ObjectMapper();
response.getWriter().write(mapper.writeValueAsString(myDto));

Maybe that's all your writeResponse should do. Change it to something like

  private void writeResponse(Object objectToWrite , ResourceResponse response){
        try {

            ObjectMapper mapper = new ObjectMapper();
            response.getWriter().write(mapper.writeValueAsString(objectToWrite));
        }
        catch (final JsonGenerationException e) {
            log.error(e.getMessage());
        } catch (final JsonMappingException e) {
            log.error(e.getMessage());
        } catch (final IOException e) {
            log.error(e.getMessage());
        }
    }

and let the caller decide which DTO to create. If you want to abstract away the logic that chooses which DTO to create, then you can do that in a separate method. Your controller at that point is then just delegating to those two methods.

Upvotes: 1

Related Questions