在Springboot中,某些字段未在JSON中解析/反序列化

时间:2018-12-01 13:50:41

标签: java json spring-boot jackson

我正在使用以下JSON通过springboot代码进行解析:

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

但是在解析/反序列化时,我得到的是学生对象:

  

学生[id = 123,主题=空,名称=名称[名字=空,   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");
    }
    }

学生Bean类:

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 + "]";
    }
}

名称Bean类:

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。)在将私有字段设为public时,代码运行良好。        我将这些字段设置为public-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

我只想知道我在哪里做错了。我到处都有公共吸气者和二传手。

5 个答案:

答案 0 :(得分:2)

重新格式化您的JSON输入以具有驼峰式大小写键:

SqlCommand command = new SqlCommand(@"
    DECLARE @dateToCheck datetime = dateadd(month, 1, datefromparts(@year, @month, 1));
    SELECT p.name, dtc.cost_price, p.date_created
    FROM [dbo].[Company_Local_Invoice_] claidig
    JOIN Type_Company dtc on claidig.ID = dtc.id 
    WHERE p.date_created < @dateToCheck
    AND (p.date_left is null or p.date_left >= @dateToCheck)
", conn);
command.Parameters.Add("@month", SqlDbType.Int).Value = month;
command.Parameters.Add("@year", SqlDbType.Int).Value = year;

答案 1 :(得分:1)

这现在正在工作。修复方法是将属性名称和JSON都保留为小写,以便按Jens,James和Kamil的建议正确反序列化字段。一世  更改了属性名称,如下所示:

private String Subject;     -->  private String subject; 
private String Firstname;   -->  private String firstname;
private String Middlename;  -->  private String middlename;
private String Lastname;    -->  private String lastname;

答案 2 :(得分:1)

使用@JsonProperty注释将json中的属性名称映射到java中的属性名称:

@JsonProperty("Firstname")
private String firstname;
@JsonProperty("Middlename")
private String middlename;
@JsonProperty("Lastname")
private String lastname;

答案 3 :(得分:1)

json不被大写的属性的第一个字符接受的原因是因为jackson库正在从对应于json的类的getter和setter解析属性名称。 Jackson通过将'get'之后的文本的前导字符转换为小写来构造属性名称(来自Java端的getter方法)。 例如: Student类中的getSubject保留在设置为“ subject”的属性中。

使用json发送发布请求时,会将json中的属性与属性集进行比较。只有与该属性集匹配的那些属性名称才会将其值从json添加到相应的java属性。当您使用json属性名称“ Subject”发布请求时,jackson不会对此进行反序列化。由于“主题”属性名称与属性集中的“主题”不匹配。这就是为什么这些属性最初为null的原因。

以上是默认行为。要覆盖此行为,您可以使用@JsonProperty批注将java属性映射到所需的json属性名称:

@JsonProperty("Subject")
String Subject;

否则请使用以小写字母开头的json属性名称。例如:用'subject'代替'Subject'

主要人种情况的转换可以在 com.fasterxml.jackson.databind.util.Beanutil类。以下方法可以做到这一点:

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属性的属性名称比较可以在下面的代码中找到(com.fasterxml.jackson.databind.deser.BeanDeserializer类中的deserializeFromObject函数。由于时间太长,我没有粘贴整个函数)。变量p对应于Jsonparser,beanProperties包含从getter和setter解析的属性名,deserializeAndSet方法将json属性值设置为java bean:

 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);

答案 4 :(得分:0)

在我的例子中,我用几个字段(并非 Pojo 中的所有字段)覆盖了 Springboot 应用程序中的 toString 方法。当我删除 toString 方法时它工作正常