0

Trying to map JSON data (see data.json below) to a Java POJO Class using Jackson Mapper. Getting the following error during de-serialization. I am not sure what it means. Please advise.

org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Can not deserialize instance of org.springframework.social.test.api.impl.AccountList out of START_OBJECT token
 at [Source: java.io.BufferedInputStream@c3020c; line: 2, column: 3]; nested exception is org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of org.springframework.social.test.api.impl.AccountList out of START_OBJECT token
 at [Source: java.io.BufferedInputStream@c3020c; line: 2, column: 3]
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readJavaType(MappingJacksonHttpMessageConverter.java:169)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.read(MappingJacksonHttpMessageConverter.java:161)
    at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:94)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:460)
    at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:228)
    at org.springframework.social.test.api.impl.AccountTemplate.getAccounts(AccountTemplate.java:44)
    at org.springframework.social.test.api.impl.AccountTemplateTest.getAccounts_current_user(AccountTemplateTest.java:24)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of org.springframework.social.test.api.impl.AccountList out of START_OBJECT token
 at [Source: java.io.BufferedInputStream@c3020c; line: 2, column: 3]
    at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:219)
    at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:212)
    at org.codehaus.jackson.map.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:246)
    at org.codehaus.jackson.map.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:204)
    at org.codehaus.jackson.map.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:194)
    at org.codehaus.jackson.map.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:30)
    at org.codehaus.jackson.map.ObjectMapper._unwrapAndDeserialize(ObjectMapper.java:2802)
    at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2730)
    at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1923)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readJavaType(MappingJacksonHttpMessageConverter.java:166)
    ... 31 more


JUnit Test Class

@Test
    public void getAccounts() {
        mockServer.expect(requestTo("api"))
        .andExpect(method(GET))
        .andExpect(header("Authorization", "Bearer someAccessToken"))
        .andRespond(withSuccess(jsonResource("data.json"), MediaType.APPLICATION_JSON));

        List<Account> accounts = tester.operations().getAccounts();
        assertEquals(4, accounts.size());

        Account account = accounts.get(0);

        assertEquals(new Long(9880), account.getId());
        assertEquals("My Account", account.getAlias());
        assertEquals("FULL", account.getPermissions());
        assertEquals("USER", account.getType());
        assertEquals(new Character('U'),account.getStatus());

        Account account1 = accounts.get(1);
        assertEquals(new Long(9887),account1.getId());
        assertEquals("Account",account1.getAlias());
        assertEquals("FULL",account1.getPermissions());
        assertEquals("USER",account1.getType());
        assertEquals(new Character('U'),account1.getStatus());

        Account account2 = accounts.get(2);
        assertEquals(new Long(00008),account2.getId());
        assertEquals("Mom's Account",account2.getAlias());
        assertEquals("FULL",account2.getPermissions());
        assertEquals("USER",account2.getType());
        assertEquals(new Character('U'),account2.getStatus());

        Account account3 = accounts.get(3);
        assertEquals(new Long(00009),account3.getId());
        assertEquals("Steph's Account",account3.getAlias());
        assertEquals("FULL",account3.getPermissions());
        assertEquals("USER",account3.getType());
        assertEquals(new Character('U'),account3.getStatus());

//The method used to configure ObjectMapper

    @Override
    protected MappingJacksonHttpMessageConverter getJsonMessageConverter() {
            MappingJacksonHttpMessageConverter converter = super.getJsonMessageConverter();
            objectMapper = new ObjectMapper();
            //UnComment if root element is not required
            objectMapper.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE);
            objectMapper.registerModule(new TestModule());
            converter.setObjectMapper(objectMapper);
            return converter;
    }

The above error goes away and It works if the following 3 lines are removed from data.json

The lines causing problem.

{
  "accounts": {
    "account":



Entire data json File

{
  "accounts": {
    "account": [
      {
        "id": "9880,
        "alias": "My Account",
        "permissions": "FULL",
        "type": "USER",
        "status": "U"
      },
      {
        "id": "9887",
        "alias": "Account",
        "permissions": "FULL",
        "type": "USER",
        "status": "U"
      },
      {
        "id": "00008",
        "alias": "Mom's Account",
        "permissions": "FULL",
        "type": "USER",
        "status": "U"
      },
      {
        "id": "00009",
        "alias": "Steph's Account",
        "permissions": "FULL",
        "type": "USER",
        "status": "U"
      }
    ]
  }
}

2 Answers 2

1

Jackson is attempting to deserialise the JSON into the AccountList type. I'm guessing this type maps to an array in JSON, so Jackson is expecting a '[' next in the stream, however your JSON begin with a '{' (aka the START_OBJECT token).

Basically your JSON doesn't match the type you're trying to deserialise into. For it to match I'd expect the target type to be something like:

class SomeClassName {
    AccountList accounts;
    [...]
}
Sign up to request clarification or add additional context in comments.

3 Comments

AccountList Class is a sub class of ArrayList e.g. AccountList extends ArrayList<Account>. Maybe this is the wrong approach for the given json data structure?
Then it will get serialised as a JSON array, but your JSON is an object at the outer level, not an array. The JSON needs to be serialised into a class which has an accounts field. I've updated my answer.
class AccountList{ private List<Account> account; /** Accessor **/ is the solution.
0

The solution is:

@JsonRootName(value="accounts")
public class AccountList implements Serializable{

    private static final long serialVersionUID = 1L;
private ArrayList<Account> account;

public AccountList(ArrayList<Account> account){
    this.account = account;
}
public ArrayList<Account> getAccount() {
    return account;
}

public void setAccount(ArrayList<Account> account) {
    this.account = account;
}

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.