2

I am consuming a spring boot application, On hitting the "/test/api" rest end point with a GET request from Postman, I am getting below error:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "userName" (class com.example.MyPojo), not marked as ignorable (0 known properties: ])

The service I am trying to consume produces response in below format.

@Getter
@Setter
public class MyResponse extends MyPojo {

    int responseCode;
    String responseMessage;
    List<MyPojo> output;
}
public class MyPojo{
}
public class User extends MyPojo {

    private String id;

    @NotBlank
    private String userName;

    private String companyId;
}

My Controller class looks like something below.

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;

@RestController
@RequestMapping("/test")
public class SampleRestController {

    @GetMapping("/api")
    public MyResponse testApi(){

        RestTemplate restTemplate = new RestTemplate();
        String url="http://<Domain>:8085/users/active";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        HttpEntity<String> entity = new HttpEntity<String>("header",headers);
        final ResponseEntity<String> responseEntity = restTemplate.exchange( url, HttpMethod.GET, entity, String.class );

        MyResponse myResponse = null;
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility( PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        mapper.enable( DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
        try {
            myResponse = mapper.readValue(responseEntity.getBody(), MyResponse.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return myResponse;
    }

}

Please point out my mistake, I am not able to figure it out. Any help will be appreciated.

MarkD
  • 23
  • 1
  • 4
  • I tried putting @JsonIgnoreProperties(ignoreUnknown = true) over MyPojo class, which resulted response like below. ```{ "responseCode": 200, "responseMessage": "Success", "output": [ {}, {}, {} ] }``` While debugging when I inspect the myResponse I see the values of MyPojo says "Class has no fields". How can I get User attributes mapped to MyPojo? – MarkD Dec 16 '19 at 12:24
  • MyPojo is empty. How would you map something to a class without attributes? – Simon Martinelli Dec 16 '19 at 12:30
  • @MarkD - To map user attribute you need to change List output; to List output; in MyResponse model as MyPojo is empty – Akash Kumar Dec 16 '19 at 12:31
  • Your user JSON string contains userName field but it cannot find it in MyPojo class. – GnanaJeyam Dec 16 '19 at 12:34

1 Answers1

2

To map user attribute you need to have UserResponse-

@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class UserResponse extends MyPojo {

    int responseCode;
    String responseMessage;
    List<User> output;
}

Similarly, for Product you'll need ProductResponse-

@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class ProductResponse extends MyPojo {

    int responseCode;
    String responseMessage;
    List<Product> output;
}

also, define @Getter and @Setter annotation if not using currently.

@Getter
@Setter
public class User extends MyPojo {

    private String id;

    @NotBlank
    private String userName;

    private String companyId;
}
Akash Kumar
  • 642
  • 7
  • 20
  • Actually I want to keep "MyResponse" flexible, as I want to use same class to responses for other Classes like "Product", "Contacts" etc. where all my pojo classes extends MyPojo. Yes, I have defined Getter and Setter annotations for all Pojo classes. – MarkD Dec 16 '19 at 12:44
  • To achieve this, you'll need to have different DTO's i.e. ProductResponse having List, ContactsResponse having List, etc. Using Single MyResponse is not possible and not suggested. Alternatively, You can convert the response into JSON and use the output key to map to List or List as per your requirement. In this case, MyResponse is also not required. The first one i.e. using different DTO is preferred. – Akash Kumar Dec 16 '19 at 12:56
  • Thanks Akash and MarkD :) I used output key as you suggested and worked for me. – MarkD Dec 24 '19 at 11:25