-1

我只是想解析一个 json 输入,它是 AbstractList 的一个实现,包含自定义对象。但是,由于某种原因,当它遇到 CustomerDealerRecord 的反序列化器时,它永远不会超过第一个节点,然后最终抛出 StackOverflowException。我已经为此苦苦挣扎了 4 个小时,并且我已经进行了许多不同的 Google 搜索,但均无济于事。所以,我最后的努力即将来到这里。你们所有人都可以对此有所了解,我们将不胜感激。谢谢你。代码如下。

public class PhoneDeserializer extends StdDeserializer<Phone>{

public PhoneDeserializer() {
    super(Phone.class);
}

@SuppressWarnings("unchecked")
@Override
public Phone deserialize(JsonParser jp,
        DeserializationContext ctx) throws IOException,
        JsonProcessingException {
    ObjectMapper mapper = (ObjectMapper) jp.getCodec();
    return  mapper.readValue(jp, Phone.class);
}

}

--

public class CustomerDealerRecordDeserializer extends StdDeserializer<CustomerDealerRecord>{

public CustomerDealerRecordDeserializer() {
    super(CustomerDealerRecord.class);
}
@SuppressWarnings("unchecked")
@Override
public CustomerDealerRecord deserialize(JsonParser jp,
        DeserializationContext ctx) throws IOException,
        JsonProcessingException {
    ObjectMapper mapper = (ObjectMapper) jp.getCodec();
    return mapper.readValue(jp, CustomerDealerRecord.class);
}

}

-- 这是自定义列表

public class CustomerDealerRecordList extends AbstractList<CustomerDealerRecord> {
private List<CustomerDealerRecord> records = new ArrayList<CustomerDealerRecord>();
@Override
public CustomerDealerRecord get(int index) {
    // TODO Auto-generated method stub
    return records.get(index);
}

@Override
public int size() {
    // TODO Auto-generated method stub
    return records.size();
}

public boolean add(CustomerDealerRecord cdr){
    return records.add(cdr);
}

}

-- 这是控制器方法

@SuppressWarnings("unchecked")
public String getCustomerDealerReportAsExcel(HttpServletRequest req, HttpServletResponse resp){
    VelocityContext vc = new VelocityContext();
    vc.put("response", resp);

    // Jackson stuff
    CustomerDealerRecordDeserializer deser = new CustomerDealerRecordDeserializer();
    PhoneDeserializer phoneDeser = new PhoneDeserializer();

    // We have to create a module for the alias'ed class
    SimpleModule cdrModule = new SimpleModule("CustomerDealerRecord", new Version(1,0,0,null));
    SimpleModule phoneModule = new SimpleModule("Phone", new Version(1,0,0,null));

    // Add the deserializer to the module
    cdrModule.addDeserializer(CustomerDealerRecord.class, deser);
    phoneModule.addDeserializer(Phone.class, phoneDeser);

    // Now, create our mapper and then register the module to it.
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(cdrModule);
    mapper.registerModule(phoneModule);

    CustomerDealerRecordList list = null;

    try {
        JsonParser jp = mapper.getJsonFactory().createJsonParser(req.getParameter("json"));
        list = mapper.readValue(jp, CustomerDealerRecordList.class);
    } catch (JsonParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (JsonMappingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    return format(req, vc, "reports/customer_dealer_report_excel");
}

-- 这是电话模型对象

public class Phone {

    public Phone(String areaCode, String phone){
        this.areaCode = areaCode;
        this.phoneNumber = phone;
    }
    private String areaCode;
    private String phoneNumber;
    public String getAreaCode() {
        return areaCode;
    }
    public void setAreaCode(String areaCode) {
        this.areaCode = areaCode;
    }
    public String getPhoneNumber() {
        return phoneNumber;
    }
    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }
}

-- 这是 CustomerDealerRecord 模型对象

public class CustomerDealerRecord {
    private String fleetName;
    private String fleetNumber;
    private String dealerName;
    private String dealerNumber;
    private String territoryName;
    private String territoryNumber;
    private String city;
    private String state;
    private Date downTime;
    private String failureDescription;
    private String tireManufacturer;
    private String tireSize;
    private String tireType;
    private String tirePosition;
    private String category;
    private String callerName;
    private Phone callerPhone;
    private String caseNumber;
    private Date caseCloseDate;
    private String poNumber;
    private String truckNumber;
    private String trailerNumber;
    private String tractorNumber;
    private String serviceDetailStatus;
    private String refusalReason;

    public String getFleetName() {
        return fleetName;
    }

    public void setFleetName(String fleetName) {
        this.fleetName = fleetName;
    }

    public String getFleetNumber() {
        return fleetNumber;
    }

    public void setFleetNumber(String fleetNumber) {
        this.fleetNumber = fleetNumber;
    }

    public String getDealerName() {
        return dealerName;
    }

    public void setDealerName(String dealerName) {
        this.dealerName = dealerName;
    }

    public String getDealerNumber() {
        return dealerNumber;
    }

    public void setDealerNumber(String dealerNumber) {
        this.dealerNumber = dealerNumber;
    }

    public String getTerritoryName() {
        return territoryName;
    }

    public void setTerritoryName(String territoryName) {
        this.territoryName = territoryName;
    }

    public String getTerritoryNumber() {
        return territoryNumber;
    }

    public void setTerritoryNumber(String territoryNumber) {
        this.territoryNumber = territoryNumber;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public Date getDownTime() {
        return downTime;
    }

    public void setDownTime(Date downTime) {
        this.downTime = downTime;
    }

    public String getFailureDescription() {
        return failureDescription;
    }

    public void setFailureDescription(String failureDescription) {
        this.failureDescription = failureDescription;
    }

    public String getTireManufacturer() {
        return tireManufacturer;
    }

    public void setTireManufacturer(String tireManufacturer) {
        this.tireManufacturer = tireManufacturer;
    }

    public String getTireSize() {
        return tireSize;
    }

    public void setTireSize(String tireSize) {
        this.tireSize = tireSize;
    }

    public String getTireType() {
        return tireType;
    }

    public void setTireType(String tireType) {
        this.tireType = tireType;
    }

    public String getTirePosition() {
        return tirePosition;
    }

    public void setTirePosition(String tirePosition) {
        this.tirePosition = tirePosition;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }

    public String getCallerName() {
        return callerName;
    }

    public void setCallerName(String callerName) {
        this.callerName = callerName;
    }

    public Phone getCallerPhone() {
        return callerPhone;
    }

    public void setCallerPhone(Phone callerPhone) {
        this.callerPhone = callerPhone;
    }

    public String getCaseNumber() {
        return caseNumber;
    }

    public void setCaseNumber(String caseNumber) {
        this.caseNumber = caseNumber;
    }

    public Date getCaseCloseDate() {
        return caseCloseDate;
    }

    public void setCaseCloseDate(Date caseCloseDate) {
        this.caseCloseDate = caseCloseDate;
    }

    public String getPoNumber() {
        return poNumber;
    }

    public void setPoNumber(String poNumber) {
        this.poNumber = poNumber;
    }

    public String getTruckNumber() {
        return truckNumber;
    }

    public void setTruckNumber(String truckNumber) {
        this.truckNumber = truckNumber;
    }

    public String getTrailerNumber() {
        return trailerNumber;
    }

    public void setTrailerNumber(String trailerNumber) {
        this.trailerNumber = trailerNumber;
    }

    public String getTractorNumber() {
        return tractorNumber;
    }

    public void setTractorNumber(String tractorNumber) {
        this.tractorNumber = tractorNumber;
    }

    public String getServiceDetailStatus() {
        return serviceDetailStatus;
    }

    public void setServiceDetailStatus(String serviceDetailStatus) {
        this.serviceDetailStatus = serviceDetailStatus;
    }

    public String getRefusalReason() {
        return refusalReason;
    }

    public void setRefusalReason(String refusalReason) {
        this.refusalReason = refusalReason;
    }

}

-- 示例 JSON

[
{
"fleetName":"sycamore specialzed carriers",
"fleetNumber":"CF00002760",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":null,
"state":null,
"downTime":"3000-01-01",
"failureDescription":null,
"tireManufacturer":"Continental Tire",
"tireSize":"10.00R15",
"tireType":"DRIVE",
"tirePosition":"LFO",
"category":"Dealer Location Information",
"callerName":"ANN RENNER",
"callerPhone":{
"areaCode":null,
"phoneNumber":null
},
"caseNumber":"189354",
"caseCloseDate":null,
"poNumber":null,
"truckNumber":null,
"trailerNumber":null,
"tractorNumber":null,
"serviceDetailStatus":"CAN",
"refusalReason":"Response time"
},
{
"fleetName":"sycamore specialzed carriers",
"fleetNumber":"CF00002760",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":null,
"state":null,
"downTime":"3000-01-01",
"failureDescription":null,
"tireManufacturer":null,
"tireSize":null,
"tireType":null,
"tirePosition":null,
"category":"Dealer Location Information",
"callerName":"ANN RENNER",
"callerPhone":{
"areaCode":null,
"phoneNumber":null
},
"caseNumber":"189354",
"caseCloseDate":null,
"poNumber":null,
"truckNumber":null,
"trailerNumber":null,
"tractorNumber":null,
"serviceDetailStatus":"ACT",
"refusalReason":null
},
{
"fleetName":"sycamore specialzed carriers",
"fleetNumber":"CF00002760",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":null,
"state":null,
"downTime":"3000-01-01",
"failureDescription":null,
"tireManufacturer":"Continental Tire",
"tireSize":"295/75R22.5",
"tireType":"BIAS",
"tirePosition":"LMI",
"category":"Service Call",
"callerName":" ",
"callerPhone":{
"areaCode":null,
"phoneNumber":null
},
"caseNumber":"189240",
"caseCloseDate":null,
"poNumber":null,
"truckNumber":null,
"trailerNumber":null,
"tractorNumber":null,
"serviceDetailStatus":"CAN",
"refusalReason":"Other"
},
{
"fleetName":"sycamore specialzed carriers",
"fleetNumber":"CF00002760",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":null,
"state":null,
"downTime":"3000-01-01",
"failureDescription":null,
"tireManufacturer":"Continental Tire",
"tireSize":"295/75R22.5",
"tireType":"DRIVE",
"tirePosition":"LMI",
"category":"Service Call",
"callerName":" ",
"callerPhone":{
"areaCode":null,
"phoneNumber":null
},
"caseNumber":"189240",
"caseCloseDate":null,
"poNumber":null,
"truckNumber":null,
"trailerNumber":null,
"tractorNumber":null,
"serviceDetailStatus":"ACT",
"refusalReason":null
},
{
"fleetName":"TEST CUSTOMER",
"fleetNumber":"123ee22a",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":null,
"state":null,
"downTime":"3000-01-01",
"failureDescription":null,
"tireManufacturer":null,
"tireSize":null,
"tireType":null,
"tirePosition":null,
"category":"Service Call",
"callerName":"JASON MA",
"callerPhone":{
"areaCode":"123",
"phoneNumber":"222"
},
"caseNumber":"189328",
"caseCloseDate":"2012-01-03",
"poNumber":null,
"truckNumber":null,
"trailerNumber":null,
"tractorNumber":null,
"serviceDetailStatus":"ACT",
"refusalReason":"Other"
},
{
"fleetName":"TEST CUSTOMER",
"fleetNumber":"123ee22a",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":"ST LOUIS",
"state":"MO",
"downTime":"3000-01-01",
"failureDescription":"REPAIR IF POSSIBLE",
"tireManufacturer":"Continental Tire",
"tireSize":"11R22.5",
"tireType":"RADIAL",
"tirePosition":"LRI",
"category":"Service Call",
"callerName":"BJ TEST",
"callerPhone":{
"areaCode":"314",
"phoneNumber":"592-3129"
},
"caseNumber":"189341",
"caseCloseDate":"2012-06-19",
"poNumber":null,
"truckNumber":null,
"trailerNumber":"34",
"tractorNumber":"12",
"serviceDetailStatus":"CAN",
"refusalReason":"Product not available"
},
{
"fleetName":"TEST CUSTOMER",
"fleetNumber":"123ee22a",
"dealerName":null,
"dealerNumber":null,
"territoryName":null,
"territoryNumber":null,
"city":"ST LOUIS",
"state":"MO",
"downTime":"3000-01-01",
"failureDescription":"REPAIR IF POSSIBLE",
"tireManufacturer":"Continental Tire",
"tireSize":"11R22.5",
"tireType":"RADIAL",
"tirePosition":"LRI",
"category":"Service Call",
"callerName":"BJ TEST",
"callerPhone":{
"areaCode":"314",
"phoneNumber":"592-3129"
},
"caseNumber":"189341",
"caseCloseDate":"2012-06-19",
"poNumber":null,
"truckNumber":null,
"trailerNumber":"34",
"tractorNumber":"12",
"serviceDetailStatus":"ACT",
"refusalReason":null
}
]
4

2 回答 2

1

正如@bmargulies 评论的那样,PhoneDeserializer 调用(间接)PhoneDeserializer。该行将mapper.readValue(jp, Phone.class);让 Jackson 解析 Phone 类的反序列化器,它恰好是 PhoneDeserializer。您根本不需要 Phonedeserializer 类,Jackson 会正确处理您的电话类。

于 2012-12-10T14:44:04.467 回答
0

是的,最初我没有使用反序列化器,正如@pgelinas 所说,它不是必需的。那是我玩弄东西后得到的地方。它没有用。根本的问题是我不得不重新使用 mapper.convertValue 并给 Phone 类一个公共的无参数构造函数。基本上,我是个白痴,只是过度分析了简单的东西。

于 2012-12-12T15:45:18.097 回答