Java Jackson对象映射器在正确的变量名上失败

时间:2019-02-04 19:36:26

标签: java json jackson dto objectmapper

注意:我知道变量的名称不正确。我正在清理另一个将这些列为成员变量的开发人员的旧代码。它们将被正确命名,是的,我知道我需要为此添加注释,但是我在这里寻找的是关于变量为何为EmployeeId的解释,它在寻找EmployeeID,但是找到了不存在的变量mEmployeeId。顺便说一句,这发生在服务器上,而不仅仅是在IDE中。

由于某些未知原因-修改变量名,保存,重新启动,使缓存无效之后,一切-杰克逊无法映射到适当的变量名。我正在为此使用intelliJ和Java。

错误:

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的情况下,它仍然在寻找世界?我认为无效/重新启动将解决此问题,但是没有解决

2 个答案:

答案 0 :(得分:1)

答案是, 通常是这样:注意您编写的代码。

获取器和设置器将字段公开为m *(其中*是实际的字段名称)。

看看这个:

getmEmployeeId(
   ^
   |

这是字母'm'。

因此,该字段名称显示为“ mEmployeeId”

更多详细信息:
方法返回的值与getter公开的值的名称无关。 Java要求getter名称的格式为“ getFieldName”,并且 setter nanes的格式为“ setFieldName” 其中,“ FieldName”是不属于方法名称的“ get”或“ set”部分的任何值。

这被称为“ JavaBean命名约定”,如果您使用Java编写代码并使用任何第三方Java库,则您必须同时理解并遵守它。

答案 1 :(得分:0)

要将JSON键与POJO属性Jackson匹配使用PropertyNamingStrategy。在您的JSON中,我们至少可以找到两种策略:

  1. SNAKE_CASEpage_sizeerror_message等)
  2. UPPER_CAMEL_CASEEmployeeIdDepartmentId等)

从另一面来看,POJO类提供了第三种策略:

  1. “ m” + UPPER_CAMEL_CASEmEmployeeIdmDepartmentId等)

这就是JSONPOJO不匹配的原因。要使其正常工作,您需要实施新的策略,如下所示:

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使用自定义映射。

另请参阅:

  1. Spring Jackson property naming strategy
  2. PropertyNamingStrategy
  3. More Jackson Annotations