我正在使用以下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
我只想知道我在哪里做错了。我到处都有公共吸气者和二传手。
答案 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 方法时它工作正常