0

I'm trying to parse a json string like the one below but I'm getting an error when the rest endpoint is hit

Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $

{
  "resources": [
{
  "resourceType": "Car",
  "resourceId": "Car1"
},
{
  "resourceType": "Truck",
  "resourceId": "Truck1"
}
],
 "topics": [
   "some_data",
   "some_event"
]
}


@PostMapping(value = "/subscribe", consumes = MediaType.APPLICATION_JSON_VALUE)
public void create(@RequestBody String subscriptionRequest)
        throws Exception
{

    SubscriptionRequest request = new Gson().fromJson(subscriptionRequest, SubscriptionRequest.class); 

    if ( request.getResources().isEmpty() || request.getTopics().isEmpty() )
    {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
    }
    other code ....
}


public class SubscriptionRequest
{
private List<Resources> resources = null;

private List<String> topics = null;

public SubscriptionRequest()
{
    super();
}

public List<Resources> getResources()
{
    return this.resources;
}

public void setResources(List<Resources> resources)
{
    this.resources = resources;
}

public List<String> getTopics()
{
    return this.topics;
}

public void setTopics(List<String> topics)
{
    this.topics = topics;
}

}

public class Resources {

    private List<Resource> resources = null;

    private int resourceId;

    public Resources() 
    {
        super();
    }

    public List<Resource> getResources() {
        return this.resources;
    }

    public void setResources(List<Resource> resources) {
        this.resources = resources;
    }
}

public class Resource {

    private String resourceType;

    private String resourceId;

    public Resource()
    {
        super();
    }

    public Resource(String resourceType, String resourceId) 
    {
        this.resourceType = resourceType;
        this.resourceId = resourceId;
    }

    public String getResourceType() 
    {
        return this.resourceType;
    }

    public void setResourceType(String resourceType) 
    {
        this.resourceType = resourceType;
    }

    public String getResourceId() 
    {
        return this.resourceId;
    }

    public void setResourceId(String resourceId) 
    {
        this.resourceId = resourceId;
    }
}

public class AppConfig extends WebMvcConfigurerAdapter
{
@Override
public void addCorsMappings(CorsRegistry registry) {
  registry.addMapping("/**")
      .allowedOrigins("*")
      .allowedMethods("POST", "GET",  "PUT", "OPTIONS", "DELETE")
      .allowedHeaders("X-Requested-With,Content-Type,Accept,Origin");
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    GsonHttpMessageConverter msgConverter = new GsonHttpMessageConverter();
    Gson gson = new GsonBuilder().setPrettyPrinting().create(); 
    msgConverter.setGson(gson);
    converters.add(msgConverter);
}
}   
3
  • How the Resources class looks like? Why its name is plural? Commented Feb 12, 2018 at 8:48
  • I have added Resources class Commented Feb 12, 2018 at 9:02
  • What I see now is that you need to have List<Resource> SubscriptionRequest class to match your expected payload. You don't need Resources class I would say. Commented Feb 12, 2018 at 9:57

1 Answer 1

1

Normally, you'd be injecting the deserialized type directly:

public void create(@RequestBody SubscriptionRequest subscriptionRequest)

and Spring takes care of deserializing it. Here, you expect a string, so Spring attempt to read the JSON input, which is an object, and deserialize it as a string, so it breaks (Expected a string but was BEGIN_OBJECT).

Try surrounding the entire input in double quotes:

"{
  "resources": [
{
  "resourceType": "Car",
  "resourceId": "Car1"
},
{
  "resourceType": "Truck",
  "resourceId": "Truck1"
}
],
 "topics": [
   "some_data",
   "some_event"
]
}"

This will likely resolve your immediate issue, but isn't what you want to do. Instead you should likely leave it to Spring as described above.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.