Некоторые поля не анализируются / десериализуются в JSON в Springboot - PullRequest
0 голосов
/ 01 декабря 2018

Я использую приведенный ниже JSON для анализа моего кода Springboot:

{
    "id" :123, 
    "Subject" : "English",
    "name": {
    "Firstname": "Hemant",
    "Middlename": "kumar", 
    "Lastname": "Mamod"
    }
}

Но при разборе / десериализации я получаю это в объекте Student:

Student [id = 123, Subject = null, name = Name [Firstname = null, Middlename = null, Lastname = null]]

У меня везде есть общедоступные методы получения и установки, что делает каждое поле подходящимдля десериализации.Я имею в виду это - https://www.baeldung.com/jackson-field-serializable-deserializable-or-not

Ниже приведен фрагмент кода, который я использую:

Restcontroller:

    package com.example.demo;
    import java.util.*;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.http.MediaType;
    import org.springframework.web.bind.annotation.*;


    @SpringBootApplication
    @RestController
    public class Demo1Application {


    @Autowired
    Student student;
    List<Student> students = new ArrayList<>();


    @RequestMapping(value="/saveStudent", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
    public String savestudent (@RequestBody Student s1) {

        System.out.println(s1);
        return "success";
    }   


    public static void main(String[] args) {
        SpringApplication.run(Demo1Application.class, args);
        System.out.println("Hello");
    }
    }

Student Bean Class:

package com.example.demo;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Student {
    int id;
    String Subject;

    @Autowired
    @Qualifier("name")
    Name name;


    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getSubjects() {
        return Subject;
    }
    public void setSubject(String subject) {
        Subject = subject;
    }

    public void setName(Name name) {
        this.name = name;  
    }
    public Name getName() {  
        return name  ;
    }
@Override
public String toString() {
    return "Student [id=" + id + ", Subject=" + Subject + ", name=" + name + "]";
    }
}

Name Bean Class:

package com.example.demo;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
@Qualifier("name")
public class Name {
    private String Firstname;
    private String Middlename;
    private String Lastname;

    public Name() {
        System.out.println("Name Object created");
    }

    public String getFirstname() {
        return Firstname;
    }
    public void setFirstname(String firstname) {
        Firstname = firstname;
    }
    public String getMiddlename() {
        return Middlename;
    }
    public void setMiddlename(String middlename) {
        Middlename = middlename;
    }
    public String getLastname() {
        return Lastname;
    }
    public void setLastname(String lastname) {
        Lastname = lastname;
    }

    public Name setfullname(String Fname, String Mname, String Lname) {
        Firstname = Fname;
        Middlename = Mname;
        Lastname = Lname;
        return this;
    }

    @Override
    public String toString() {
        return "Name [Firstname=" + Firstname + ", Middlename=" + Middlename + ", Lastname=" + Lastname + "]";
    }

}

PS -

1.) Если сделать закрытые поля общедоступными, код работает нормально.Я сделал эти поля общедоступными - id, Subject, name, Firstname, Middlename, Lastname

2.) Я уже знаю, что добавление ниже двух в application.properties даст мне правильный вывод: spring.jackson.deserialization.fail-on-unknown-properties = false spring.jackson.mapper.accept-case-insensitive-properties = true

Я просто хочу знать, где именно я делаю что-то неправильно.У меня есть публичные геттеры и сеттеры везде

Ответы [ 4 ]

0 голосов
/ 02 декабря 2018

Причина, по которой json не был принят с первым символом атрибутов в верхнем регистре, заключается в том, что библиотека Джексона разрешает имена свойств из методов получения и установки класса, соответствующего json.Джексон создает имена свойств путем преобразования начальных символов текста, следующих за «get», в нижний регистр (из метода get в стороне java).Например: getSubject в классе Student хранится в свойстве, установленном как «subject».

Когда почтовый запрос отправляется с помощью json, атрибуты в json сравниваются с набором свойств.Только те имена атрибутов, которые соответствуют этому набору свойств, будут иметь свои значения, добавленные из json к соответствующему атрибуту java.Когда вы отправляете запрос с именем атрибута json 'Subject', Джексон не будет десериализовать это.Так как имя атрибута 'Subject' не совпадает с 'subject' в наборе свойств.Вот почему для этих атрибутов изначально было значение null.

Выше сказанное является поведением по умолчанию. Чтобы переопределить это поведение, вы можете сопоставить свойство java с желаемым именем атрибута json, используя аннотацию @JsonProperty:

@JsonProperty("Subject")
String Subject;

В противном случае используйте имя атрибута json, начинающееся со строчной буквы. Например: вместо 'субъекта' вместо 'субъекта'

Преобразование в регистр начальных символов можно увидеть в com.fasterxml.jackson.databind.util.Beanutil class.The метод ниже делает это:

protected static String legacyManglePropertyName(final String basename, final int offset)
    {
        final int end = basename.length();
        if (end == offset) { // empty name, nope
            return null;
        }
        // next check: is the first character upper case? If not, return as is
        char c = basename.charAt(offset);
        char d = Character.toLowerCase(c);

        if (c == d) {
            return basename.substring(offset);
        }
        // otherwise, lower case initial chars. Common case first, just one char
        StringBuilder sb = new StringBuilder(end - offset);
        sb.append(d);
        int i = offset+1;
        for (; i < end; ++i) {
            c = basename.charAt(i);
            d = Character.toLowerCase(c);
            if (c == d) {
                sb.append(basename, i, end);
                break;
            }
            sb.append(d);
        }
        return sb.toString();
    }

Сравнение имени свойства с атрибутом json можно найти в следующем коде (функция deserializeFromObject в com.fasterxml.jackson.databind.deser.Класс BeanDeserializer. Я не вставляю всю функцию, так как она слишком длинная).Переменная p соответствует Jsonparser, а beanProperties содержит имена свойств, разрешенные из getter и setter, метод deserializeAndSet устанавливает значение атрибута json для bean-компонента java:

 if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
            String propName = p.getCurrentName();
            do {
                p.nextToken();
                SettableBeanProperty prop = _beanProperties.find(propName);
                if (prop != null) { // normal case
                    try {
                        prop.deserializeAndSet(p, ctxt, bean);
                    } catch (Exception e) {
                        wrapAndThrow(e, bean, propName, ctxt);
                    }
                    continue;
                }
                handleUnknownVanilla(p, ctxt, bean, propName);
            } while ((propName = p.nextFieldName()) != null);
0 голосов
/ 01 декабря 2018

Это сейчас работает.Было исправлено сохранение имени свойства и JSON в нижнем регистре для правильной десериализации полей, как это было предложено Йенсом, Джеймсом и Камилем.Я изменил имена свойств следующим образом:

private String Subject;     -->  private String subject; 
private String Firstname;   -->  private String firstname;
private String Middlename;  -->  private String middlename;
private String Lastname;    -->  private String lastname;
0 голосов
/ 01 декабря 2018

Используйте аннотацию @JsonProperty, чтобы сопоставить имя свойства в json с именем свойства в java:

@JsonProperty("Firstname")
private String firstname;
@JsonProperty("Middlename")
private String middlename;
@JsonProperty("Lastname")
private String lastname;
0 голосов
/ 01 декабря 2018

Переформатируйте входные данные JSON, чтобы получить ключи от верблюда:

{
    "id" :123, 
    "subject" : "English",
    "name": {
    "firstname": "Hemant",
    "middlename": "kumar", 
    "lastname": "Mamod"
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...