Java Json中的自定义反序列化程序

Java Json中的自定义反序列化程序,java,json,jackson,deserialization,Java,Json,Jackson,Deserialization,我想在类级别实现到下面POJO的自定义Json映射 @JsonDeserialize(using = DeviceDeserializer.class) public class Pojo { private String device; private String port; private String reservbleBw; *default constructor, getter and setters* } 下面是我的Json文件 [ { "

我想在类级别实现到下面POJO的自定义Json映射

@JsonDeserialize(using = DeviceDeserializer.class)
 public class Pojo {
   private String device;
   private String port;
   private String reservbleBw;
   *default constructor, getter and setters*
 }
下面是我的Json文件

[
  {
   "Device":"ABCD",
   "ifces":[
     {
      "port":"ABCD:1/2/0",
      "reservableBW":"1000",
      "capabilites":[ "MPLS" ]
    },
    {
      "port":"ABCD:1/2/1",
      "reservableBW":"100",
      "capabilites":[ "ETHERNET" ]
    }
  ]
 }
]
现在,当“能力”是“以太网”时,我只需要映射端口和reservableBw。我看了一些自定义反序列化器的示例,但不知道如何传递JsonParser和反序列化上下文的值。我无法理解下面这一行

  public Pojo deserialize(JsonParser jParser, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
 // custom deserializer implementation
}

有两种方法可以解决您的问题:

方法1:使用中间对象映射器:我已经为您的问题创建了一个演示,请参见

创建一个中间对象来映射原始JSON

public class SfPojoDto {
    private String device;
    private List<Ifce> ifces;
}

public class Ifce {
    private String port;
    private String reservableBW;
    private String[] capabilites;
}
公共类SfPojoDto{
专用字符串设备;
私人名单国际单项体育联合会;
}
公共类Ifce{
专用字符串端口;
私有字符串reservableBW;
私有字符串[]功能;
}
然后使用自定义反序列化器首先映射它并转换为目标对象

public class DeviceDeserializer extends JsonDeserializer<SfPojo> {
    @Override
    public SfPojo deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        // while (p.nextToken()!=null) {
        //     if (p.getCurrentToken()==)
        // }
        String temp = p.readValueAsTree().toString();
        ObjectMapper mapper = new ObjectMapper();
        SfPojoDto sfPojoDto = mapper.readValue(temp, SfPojoDto.class);
        SfPojo sfPojo = new SfPojo();
        sfPojo.setDevice(sfPojoDto.getDevice());
        List<Ifce> ifceList = sfPojoDto.getIfces();
        for (Ifce ifce : ifceList) {
            List<String> capabilities = Arrays.asList(ifce.getCapabilites());
            if (capabilities.contains("ETHERNET")) {
                sfPojo.setPort(ifce.getPort());
                sfPojo.setReservbleBw(ifce.getReservableBW());
                return sfPojo;
            }
        }
        return sfPojo;
    }
}
公共类DeviceDeserializer扩展JsonDeserializer{
@凌驾
公共SfPojo反序列化(JSONP解析器,反序列化上下文ctxt)
抛出IOException、JsonProcessingException{
//while(p.nextToken()!=null){
//如果(p.getCurrentToken()=)
// }
字符串温度=p.readValueAsTree().toString();
ObjectMapper mapper=新的ObjectMapper();
SfPojoDto SfPojoDto=mapper.readValue(temp,SfPojoDto.class);
SfPojo SfPojo=新的SfPojo();
setDevice(sfPojoDto.getDevice());
List-ifceList=sfPojoDto.getIfces();
for(Ifce-Ifce:ifceList){
列表功能=Arrays.asList(ifce.getCapabilites());
if(能力.包含(“以太网”)){
setPort(ifce.getPort());
setReservablebw(ifce.getReservableBW());
返回sfPojo;
}
}
返回sfPojo;
}
}
方法2:您可以使用JsonParser来操作JSON字符串,但此方法更复杂,您可以引用:

您的模型:

public class Ifce {

    public String port;
    public String reservableBW;
    public List<String> capabilites = null;

}

public class Device {
    public String device;
    public List<Ifce> ifces = null;

}
公共类Ifce{
公共字符串端口;
公共字符串reservableBW;
公共列表能力=空;
}
公共类设备{
公共字符串设备;
公共列表ifces=null;
}
然后像这样使用objectMapper:

objectMapper = new ObjectMapper()
Device device = objectMapper.readValue(yourJsonData, Device.class)
List<Ifce> deviceList  = device.ifces.find { it.capabilites.contains("ETHERNET")}
objectMapper=newObjectMapper()
Device Device=objectMapper.readValue(yourJsonData,Device.class)
List deviceList=device.ifces.find{it.capabilites.contains(“以太网”)}

不清楚“我不知道如何传递JsonParser和反序列化上下文的值”是什么意思。您注册了自定义反序列化程序,Jackson将使用该反序列化程序,您不需要传递任何内容,Jackson将向您传递这些值。Jackson将向您传递这些值吗?我正在从文件中读取Json对象。现在我如何使用json解析器来解析呢?您能详细说明一下吗?因为我从来没有用过这个如果你使用自定义反序列化程序,为什么你不知道基本情况是如何工作的?在每一个Jackson教程中,几乎都会向.JsonParser传递json属性,以便我可以使用它返回自定义对象。但我也不知道他们是如何得到这些价值观的?谁知道它在哪里经过?这有点让人困惑,因为这两个参数来自何处。这将映射所有端口,但我只想要那些具有以太网功能的端口。这是我当前的实现。我相信找到您感兴趣的项目比过度设计解析器更容易。。我还没有测试特定的find函数,但是类似的东西应该可以完成您正在寻找的功能。上面的代码是否对整个文件进行了两次迭代?如果是这样的话,我不想那样做。它将JSON反序列化为POJO,并将所有数据反序列化为设备对象2。创建并列出包含ETHERNET的所有Ifces对象,读取Json一次。一切正常。但我只想知道jsonparser是如何得到它的值的。调用这个customdeserializer传递这些参数是什么吗?您可以检查完整的jsonparser javadoc。通常,您可以使用
p.readValueAsTree().toString()
获取所有字符串,或者使用
p.getText()
获取属性字符串,或者您可以通过
p.nextToken()
迭代所有标记。我不想知道解析器。一旦得到包含数据的解析器对象,我就可以处理它。你怎么叫它工作?我还是不明白你的意思。你是说Jackson是如何调用自定义反序列化程序的?是的,参数也是,temp的值是多少?