Получение JsonMappingException при отправке данных для просмотра
Я пытаюсь показать данные БД на моей веб-странице.
Я сделал следующий код, когда GET-запрос к @RequestMapping(value = "/api/binder")
.
но когда запрос запроса пришел к этому методу, он будет извлекать данные (у меня есть печать на консоли и хорошо отображена), но она не отображается на мой вызов Java Script Ajax, это показывает мне ошибку.
Ниже приведен мой код для извлечения данных:
@Autowired
IBinderViewRepository repository;
@RequestMapping(method= RequestMethod.GET)
public @ResponseBody
List<BinderResponse> getBinders(){
List<BinderView> binders = repository.getBinders();
List<BinderResponse> responses = new ArrayList<>();
ModelMapper mapper = Mapper.getInstance();
for(int i = 0; i < binders.size(); i++){
System.out.println("In Loop");
BinderResponse response = mapper.map(binders.get(i),BinderResponse.class);
System.out.println("Data :: " + response.getBinderName());
responses.add(response);
}
return responses;
}
но он показывает мне следующую ошибку:
HTTP Status 500 - Could not write JSON: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.ngl.dto.outgoing.BinderResponse["valid"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.ngl.dto.outgoing.BinderResponse["valid"])
Вот вызов ajax от нокаута js:
ajax.get('api/binder').done(function(response){ ... }
Здесь BinderView and BinderResponse
имеют одинаковые поля:
private String binderName;
private String binderAddress1;
а также в том, и в другом.
и repository.genBinders()
приносят данные из БД.
Вот способ вставки и отлично работает для меня:
@RequestMapping(method= RequestMethod.POST,consumes = "application/json")
public @ResponseBody
IWebApiResponse addBinder(@RequestBody AddBinderForm binder){
.....
}
Должен ли я поставить любой json annotation on my BinderResponse class ?
Я не понимаю, где я ошибаюсь? Кто-нибудь просит меня.
ОБНОВЛЕНИЕ:
public class BinderResponse extends WebApiResponseBase {
private String binderName;
private String binderAddress1;
public String getBinderName() {
return binderName;
}
public void setBinderName(String binderName) {
this.binderName = binderName;
}
public String getBinderAddress1() {
return binderAddress1;
}
public void setBinderAddress1(String binderAddress1) {
this.binderAddress1 = binderAddress1;
}
}
BinderView:
public class BinderView extends BaseView {
private String binderName;
private String binderAddress1;
public String getBinderName() {
return binderName;
}
public void setBinderName(String binderName) {
this.binderName = binderName;
}
public String getBinderAddress1() {
return binderAddress1;
}
public void setBinderAddress1(String binderAddress1) {
this.binderAddress1 = binderAddress1;
}
}
В консоли он печатает данные /BinderName:
In Loop
Data :: ada
In Loop
Data :: tya
Новое обновление:
Вот BaseView:
@MappedSuperclass
public abstract class BaseView implements IEntity {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name="id")
private long id;
public long getId() {
return id;
}
public void setId(long id) {
if (this.id != 0 && this.id != id) {
throw new IllegalStateException(
"The ID must not be changed after it is set.");
}
this.id = id;
}
}
и IEntity:
public interface IEntity extends Serializable {
long getId();
void setId(long id);
}
WebApiResponseBase:
public class WebApiResponseBase implements IWebApiResponse {
private String _uri;
@Override
public String getUri() {
return _uri == null ? "" : _uri;
}
@Override
public void setUri(String uri) {
_uri = uri;
}
}
Ответы
Ответ 1
Джексон по умолчанию сериализует целую иерархию наследования объектов, т.е. поля родительского класса. В случае
public class BinderResponse extends WebApiResponseBase {
Кажется,
Could not write JSON: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.ngl.dto.outgoing.BinderResponse["valid"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]->com.ngl.dto.outgoing.BinderResponse["valid"])
Джексон пытается сериализовать поле под названием valid
из getter
, называемого isValid
(которое является обычным именем свойства bean). Однако метод геттера, по любой причине, бросает NullPointerException
.
Если вы хотите, чтобы Джексон проигнорировал его, вы можете аннотировать геттер с помощью @JsonIgnore
или вашего класса с помощью @JsonIgnoreProperties
и указать имя свойства, т.е. valid
.
Ответ 2
В моем случае, когда я использовал @JsonIgnore
исключение пропало, но проблема заключалась в том, что он больше не мог получить это значение из API Request
, а Spring проигнорировал его (очевидно, из-за @JsonIgnore
). Поэтому я исследовал проблему и выяснил, что проблема была getter
и setter
. У меня было свойство Integer
то время как мой getter
был int
. Так что, когда я изменил getter
к Integer
моя проблема решена, и ошибка исчезла.
private Integer purchaseId;
@JsonIgnore
public int getPurchaseId() {
return purchaseId;
}
public void setPurchaseId(int purchaseId) {
this.purchaseId = purchaseId;
}
Изменился на:
private Integer purchaseId;
public Integer getPurchaseId() {
return purchaseId;
}
public void setPurchaseId(Integer purchaseId) {
this.purchaseId = purchaseId;
}
Ответ 3
У меня был обратный случай, когда моя переменная была определена как "Double", а геттеры и сеттеры были "double". Изменение переменной с 'Double' на 'double' сработало для меня.
Ответ 4
@Column(name="createddate")
private Date createdDate;
@Transient
private String formatedCreatedDate;
public String getFormatedCreatedDate() {
DateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy");
return dateFormat.format(this.getCreatedDate());
}
Он выдает одно и то же исключение, потому что здесь может быть null, вызвав значение getCreatedDate(), чтобы оно не могло форматировать нулевую дату, поэтому держите нуль здесь как:
Решение
public String getFormatedCreatedDate() {
DateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy");
Date createDdate=this.getCreatedDate();
**if(createDdate!=null){
return dateFormat.format(createDdate);
}**
return "-";
}