Java Jackson 对象映射器在正确的变量名上失败
Java Jackson object mapper fails on correct variable name
注意:我知道变量没有正确命名。我正在清理另一个开发人员的旧代码,他们将这些代码列为成员变量。它们将被正确命名,是的,我知道我需要注释,但我在这里寻找的是关于为什么变量是 EmployeeId 的解释,它正在寻找 EmployeeID,但找到一个不存在的变量 mEmployeeId。顺便说一句,这发生在服务器上,而不仅仅是 IDE.
由于某些未知原因 - 在修改变量名称、保存、重新启动、使缓存无效等一切之后 - jackson 无法映射到正确的变量名称。为此,我正在使用带有 Java 的 intelliJ。
错误:
Exception in badge service getting by badgeId: Unrecognized field
"EmployeeId" (class com.companyName.attendance.entity.DTOs.badgeservice.BadgeDTO), not marked as ignorable (6 known properties: "mBadgeId", "mEmployeeId", "mLanId", "mFirstName", "mEmail", "mLastName"])
at [Source: (String)"{"backoff":null,"error_id":null,"error_message":null,"error_name":null,"has_more":false,"items":[{"EmployeeId":"888888","LanId":"NTest","FirstName":"Name","MiddleName":null,"LastName":"Test","Email":null,"Location":null,"Title":null,"Phone":null,"DepartmentId":null,"DepartmentName":null,"DepartmentNumber":null,"Groups":null,"Found":false,"BadgeId":"222222","JobTitle":null,"Picture":null,"OrgUrl":null,"Manager":null,"Coworkers":null,"DirectReports":null}],"page":null,"page_size":null,"quo"[truncated 61 chars]; line: 1, column: 113] (through reference chain: com.companyName.attendance.entity.DTOs.badgeservice.BadgeServiceResponseDTO["items"]->java.util.ArrayList[0]->com.companyName.attendance.entity.DTOs.badgeservice.BadgeDTO["EmployeeId"])
如您所见,它没有在 DTO 中找到 EmployeeId,并表示预期的字段是 mEmployeeID。但是,这是我的 DTO 变量声明:
public class BadgeDTO {
//TODO: Convert member variables to proper practice names
String BadgeId;
String EmployeeId;
String FirstName;
String LanId;
String LastName;
String Email;
public BadgeDTO(String BadgeId, String EmployeeId, String FirstName,
String LanId, String LastName, String Email) {
super();
this.BadgeId = BadgeId;
this.EmployeeId = EmployeeId;
this.FirstName = FirstName;
this.LanId = LanId;
this.LastName = LastName;
this.Email = Email;
}
public BadgeDTO() {
super();
}
public String getmBadgeId() {
return BadgeId;
}
public void setmBadgeId(String BadgeId) {
this.BadgeId = BadgeId;
}
public String getmEmployeeId() {
return EmployeeId;
}
public void setmEmployeeId(String EmployeeId) {
this.EmployeeId = EmployeeId;
}
public String getmFirstname() {
return FirstName;
}
public void setmFirstName(String FirstName) {
this.FirstName = FirstName;
}
public String getmLanId() {
return LanId;
}
public void setmLanId(String LanId) {
this.LanId = LanId;
}
public String getmLastName() {
return LastName;
}
public void setmLastName(String LastName) {
this.LastName = LastName;
}
public String getmEmail() {
return Email;
}
public void setmEmail(String Email) {
this.Email = Email;
}
@Override
public String toString() {
return "BadgeDTO [BadgeId=" + BadgeId + ", EmployeeId=" + EmployeeId +
", Firstname=" + FirstName
+ ", LanId=" + LanId + ", LastName=" + LastName + ", Email=" +
Email + "]";
}
}
现在最疯狂的是,做以下工作:
@JsonProperty("BadgeId")
String BadgeId;
@JsonProperty("EmployeeId")
String EmployeeId;
@JsonProperty("FirstName")
String FirstName;
JSON:
{
"backoff": null,
"error_id": null,
"error_message": null,
"error_name": null,
"has_more": false,
"items": [
{
"EmployeeId": "888888",
"LanId": "TName",
"FirstName": "Test",
"MiddleName": null,
"LastName": "Name",
"Email": null,
"Location": null,
"Title": null,
"Phone": null,
"DepartmentId": null,
"DepartmentName": null,
"DepartmentNumber": null,
"Groups": null,
"Found": false,
"BadgeId": "222222",
"JobTitle": null,
"Picture": null,
"OrgUrl": null,
"Manager": null,
"Coworkers": null,
"DirectReports": null
}
],
"page": null,
"page_size": null,
"quota_max": null,
"quota_remaining": null,
"total": null,
"type": null
}
所以,我已经使用上面的 JsonProperty 注释解决了这个问题,但是为什么它仍然在寻找 mEmployeeId,而它在我的整个代码中都不存在?我认为 invalidate/restart 可以解决这个问题,但没有
答案是,
通常情况下:注意您编写的代码。
getters 和 setters 将字段公开为 m*(其中 * 是实际字段名称)。
看看这个:
getmEmployeeId(
^
|
这是一封信 'm'。
因此,这会将字段名称公开为 "mEmployeeId"
更多详情:
该方法返回的值与 getter 公开的值的名称无关。
Java 要求 getter 名称的格式为 "getFieldName" 并且
setter nanes 的格式为 "setFieldName"
其中 "FieldName" 是任何不是方法名称的 "get" 或 "set" 部分的值。
这称为 "JavaBean Naming Convention",如果您在 Java 中编写代码并使用任何第三方 Java 库,您绝对必须理解并遵守它。
要将 JSON
键与 POJO
属性 Jackson
相匹配,需要使用一种名为 PropertyNamingStrategy
的方法。在你的JSON
中我们至少可以找到两种策略:
- SNAKE_CASE(
page_size
、error_message
等)
- UPPER_CAMEL_CASE(
EmployeeId
、DepartmentId
等)
从另一边POJO
class提供第三种策略:
- "m" + UPPER_CAMEL_CASE(
mEmployeeId
、mDepartmentId
等)
这就是 JSON
不匹配 POJO
的原因。为了让它发挥作用,您需要实施如下所示的新策略:
class MNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method,
String defaultName) {
return defaultName.substring(1); // remove first `m` letter
}
}
你可以这样使用:
@JsonNaming(MNamingStrategy.class)
class Clazz {
private int Id = 11;
public int getmId() {
return Id;
}
public void setmId(int id) {
this.Id = id;
}
@Override
public String toString() {
return "Clazz{" +
"Id=" + Id +
'}';
}
}
从现在开始,您可以将上面的 JSON
反序列化为给定的 POJO
。
当您使用 属性 个名称添加 @JsonProperty
注释时,您已告知 Jackson
使用自定义映射。
另请参阅:
注意:我知道变量没有正确命名。我正在清理另一个开发人员的旧代码,他们将这些代码列为成员变量。它们将被正确命名,是的,我知道我需要注释,但我在这里寻找的是关于为什么变量是 EmployeeId 的解释,它正在寻找 EmployeeID,但找到一个不存在的变量 mEmployeeId。顺便说一句,这发生在服务器上,而不仅仅是 IDE.
由于某些未知原因 - 在修改变量名称、保存、重新启动、使缓存无效等一切之后 - jackson 无法映射到正确的变量名称。为此,我正在使用带有 Java 的 intelliJ。
错误:
Exception in badge service getting by badgeId: Unrecognized field
"EmployeeId" (class com.companyName.attendance.entity.DTOs.badgeservice.BadgeDTO), not marked as ignorable (6 known properties: "mBadgeId", "mEmployeeId", "mLanId", "mFirstName", "mEmail", "mLastName"])
at [Source: (String)"{"backoff":null,"error_id":null,"error_message":null,"error_name":null,"has_more":false,"items":[{"EmployeeId":"888888","LanId":"NTest","FirstName":"Name","MiddleName":null,"LastName":"Test","Email":null,"Location":null,"Title":null,"Phone":null,"DepartmentId":null,"DepartmentName":null,"DepartmentNumber":null,"Groups":null,"Found":false,"BadgeId":"222222","JobTitle":null,"Picture":null,"OrgUrl":null,"Manager":null,"Coworkers":null,"DirectReports":null}],"page":null,"page_size":null,"quo"[truncated 61 chars]; line: 1, column: 113] (through reference chain: com.companyName.attendance.entity.DTOs.badgeservice.BadgeServiceResponseDTO["items"]->java.util.ArrayList[0]->com.companyName.attendance.entity.DTOs.badgeservice.BadgeDTO["EmployeeId"])
如您所见,它没有在 DTO 中找到 EmployeeId,并表示预期的字段是 mEmployeeID。但是,这是我的 DTO 变量声明:
public class BadgeDTO {
//TODO: Convert member variables to proper practice names
String BadgeId;
String EmployeeId;
String FirstName;
String LanId;
String LastName;
String Email;
public BadgeDTO(String BadgeId, String EmployeeId, String FirstName,
String LanId, String LastName, String Email) {
super();
this.BadgeId = BadgeId;
this.EmployeeId = EmployeeId;
this.FirstName = FirstName;
this.LanId = LanId;
this.LastName = LastName;
this.Email = Email;
}
public BadgeDTO() {
super();
}
public String getmBadgeId() {
return BadgeId;
}
public void setmBadgeId(String BadgeId) {
this.BadgeId = BadgeId;
}
public String getmEmployeeId() {
return EmployeeId;
}
public void setmEmployeeId(String EmployeeId) {
this.EmployeeId = EmployeeId;
}
public String getmFirstname() {
return FirstName;
}
public void setmFirstName(String FirstName) {
this.FirstName = FirstName;
}
public String getmLanId() {
return LanId;
}
public void setmLanId(String LanId) {
this.LanId = LanId;
}
public String getmLastName() {
return LastName;
}
public void setmLastName(String LastName) {
this.LastName = LastName;
}
public String getmEmail() {
return Email;
}
public void setmEmail(String Email) {
this.Email = Email;
}
@Override
public String toString() {
return "BadgeDTO [BadgeId=" + BadgeId + ", EmployeeId=" + EmployeeId +
", Firstname=" + FirstName
+ ", LanId=" + LanId + ", LastName=" + LastName + ", Email=" +
Email + "]";
}
}
现在最疯狂的是,做以下工作:
@JsonProperty("BadgeId")
String BadgeId;
@JsonProperty("EmployeeId")
String EmployeeId;
@JsonProperty("FirstName")
String FirstName;
JSON:
{
"backoff": null,
"error_id": null,
"error_message": null,
"error_name": null,
"has_more": false,
"items": [
{
"EmployeeId": "888888",
"LanId": "TName",
"FirstName": "Test",
"MiddleName": null,
"LastName": "Name",
"Email": null,
"Location": null,
"Title": null,
"Phone": null,
"DepartmentId": null,
"DepartmentName": null,
"DepartmentNumber": null,
"Groups": null,
"Found": false,
"BadgeId": "222222",
"JobTitle": null,
"Picture": null,
"OrgUrl": null,
"Manager": null,
"Coworkers": null,
"DirectReports": null
}
],
"page": null,
"page_size": null,
"quota_max": null,
"quota_remaining": null,
"total": null,
"type": null
}
所以,我已经使用上面的 JsonProperty 注释解决了这个问题,但是为什么它仍然在寻找 mEmployeeId,而它在我的整个代码中都不存在?我认为 invalidate/restart 可以解决这个问题,但没有
答案是, 通常情况下:注意您编写的代码。
getters 和 setters 将字段公开为 m*(其中 * 是实际字段名称)。
看看这个:
getmEmployeeId(
^
|
这是一封信 'm'。
因此,这会将字段名称公开为 "mEmployeeId"
更多详情:
该方法返回的值与 getter 公开的值的名称无关。
Java 要求 getter 名称的格式为 "getFieldName" 并且
setter nanes 的格式为 "setFieldName"
其中 "FieldName" 是任何不是方法名称的 "get" 或 "set" 部分的值。
这称为 "JavaBean Naming Convention",如果您在 Java 中编写代码并使用任何第三方 Java 库,您绝对必须理解并遵守它。
要将 JSON
键与 POJO
属性 Jackson
相匹配,需要使用一种名为 PropertyNamingStrategy
的方法。在你的JSON
中我们至少可以找到两种策略:
- SNAKE_CASE(
page_size
、error_message
等) - UPPER_CAMEL_CASE(
EmployeeId
、DepartmentId
等)
从另一边POJO
class提供第三种策略:
- "m" + UPPER_CAMEL_CASE(
mEmployeeId
、mDepartmentId
等)
这就是 JSON
不匹配 POJO
的原因。为了让它发挥作用,您需要实施如下所示的新策略:
class MNamingStrategy extends PropertyNamingStrategy {
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method,
String defaultName) {
return defaultName.substring(1); // remove first `m` letter
}
}
你可以这样使用:
@JsonNaming(MNamingStrategy.class)
class Clazz {
private int Id = 11;
public int getmId() {
return Id;
}
public void setmId(int id) {
this.Id = id;
}
@Override
public String toString() {
return "Clazz{" +
"Id=" + Id +
'}';
}
}
从现在开始,您可以将上面的 JSON
反序列化为给定的 POJO
。
当您使用 属性 个名称添加 @JsonProperty
注释时,您已告知 Jackson
使用自定义映射。
另请参阅: