Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将JSON转换为Java对象,如何用Jackson解析獾鱼约定_Java_Json_Xsd_Jackson_Badgerfish - Fatal编程技术网

将JSON转换为Java对象,如何用Jackson解析獾鱼约定

将JSON转换为Java对象,如何用Jackson解析獾鱼约定,java,json,xsd,jackson,badgerfish,Java,Json,Xsd,Jackson,Badgerfish,使用API,我收到如下JSON(现在保存到文件中): 我想从中获取Java对象。我已经用提供的xsd文件创建了Java对象。我正在运行的代码是: public static void toJava() { ObjectMapper mapper = new ObjectMapper(); try { File json = new File("C:\\temp\\JSON.json"); LEIRecordType[] type = mapper.

使用API,我收到如下JSON(现在保存到文件中):

我想从中获取Java对象。我已经用提供的xsd文件创建了Java对象。我正在运行的代码是:

public static void toJava() {
    ObjectMapper mapper = new ObjectMapper();
    try {
        File json = new File("C:\\temp\\JSON.json");
        LEIRecordType[] type = mapper.readValue(json, LEIRecordType[].class);
    } catch (JsonEOFException ex) {
        ex.printStackTrace();
    } catch (JsonMappingException ex) {
        ex.printStackTrace();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}
这就产生了以下例外情况:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "LEI" (class   org.leiroc.data.schema.leidata._2014.LEIRecordType), not marked as ignorable (5 known properties: "lei", "registration", "entity", "nextVersion", "extension"])
 at [Source: (File); line: 3, column: 14] (through reference chain: java.lang.Object[][0]->org.leiroc.data.schema.leidata._2014.LEIRecordType["LEI"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1545)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890)
at Test.JSONParser.toJava(JSONParser.java:38)
at Test.JSONParser.main(JSONParser.java:29)
LEIRecordType如下所示:

package org.leiroc.data.schema.leidata._2014;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "LEIRecordType", propOrder = {"lei", "entity", "registration", "nextVersion", "extension"})
public class LEIRecordType {

    @XmlElement(name = "LEI", required = true)
    protected String lei;

    @XmlElement(name = "Entity", required = true)
    protected EntityType entity;

    @XmlElement(name = "Registration", required = true)
    protected RegistrationType registration;

    @XmlElement(name = "NextVersion")
    protected LEIRecordNextVersionType nextVersion;

    @XmlElement(name = "Extension")
    protected ExtensionType extension;

    public String getLEI() {
        return this.lei;
    }

    public void setLEI(String paramString) {
        this.lei = paramString;
    }

    public EntityType getEntity() {
        return this.entity;
    }

    public void setEntity(EntityType paramEntityType) {
        this.entity = paramEntityType;
    }

    public RegistrationType getRegistration() {
        return this.registration;
    }

    public void setRegistration(RegistrationType paramRegistrationType) {
        this.registration = paramRegistrationType;
    }

    public LEIRecordNextVersionType getNextVersion() {
        return this.nextVersion;
    }

    public void setNextVersion(LEIRecordNextVersionType paramLEIRecordNextVersionType) {
        this.nextVersion = paramLEIRecordNextVersionType;
    }

    public ExtensionType getExtension() {
        return this.extension;
    }

    public void setExtension(ExtensionType paramExtensionType) {
        this.extension = paramExtensionType;
    }
}
我知道问题在于jackson正在锁定一个名为LEI的Java对象,该对象带有一个名为“$”的变量。但是没有。组织帮助服务说:

“$”对象始终复制相应XML元素的简单内容(即不是属性、子节点等)。 如果适用,“$”对象应始终作为JSON字符串键入

但据我所知,这不是JSON标准

我的问题是:有没有办法让jackson将其解析为LEI=“549300Q82NZ9NYNMZT63”等,而不是用变量“$”来表示和对象LEI? 一天中大部分时间都在这上面

@更新
根据客户服务,这种JSON格式显然被称为“獾鱼约定”。

由于
$
对象始终是
字符串,您可以为处理獾鱼包装对象的字符串创建自定义反序列化程序

此反序列化程序检查
字符串
值周围是否有獾鱼包装对象并将其展开。正常的
字符串
值像往常一样反序列化

public class BadgerFishDeserializer extends StdDeserializer<String> {

    private static final long serialVersionUID = 1L;

    private static final SerializedString BADGER_FISH_FIELD_NAME = new SerializedString("$");

    public BadgerFishDeserializer() {
        super(String.class);
    }

    @Override
    public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        // do we have a wrapper object?
        if (jp.isExpectedStartObjectToken()) {          
            // check if first field name is equal to '$'
            if (!jp.nextFieldName(BADGER_FISH_FIELD_NAME)) {
                ctxt.reportInputMismatch(String.class, "Expected BadgerFish field name '$', but got '%s'", jp.getCurrentName());
            }
            jp.nextValue();  // proceed to the actual value
            String value = jp.getValueAsString();  // read value as string
            jp.nextToken();  // consume END_OBJECT of wrapper object
            return value;
        }
        // else: just return string value
        return jp.getValueAsString();
    }

}
注意:如果您只想打开某些属性,可以创建一个自定义注释,并使用
BeanDeserializerModifier
检查注释,然后提供一个处理包装器对象的反序列化程序

值得思考的是:

  • 创建注释
  • 修改反序列化程序以始终期望包装器对象(在普通字符串上失败)
  • 创建一个
    反序列化修改器
  • ObjectMapper
困难的部分是:

public class BadgerFishDeserializerModifier extends BeanDeserializerModifier {

    @Override
    public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) {
        Iterator<SettableBeanProperty> props = builder.getProperties();
        while (props.hasNext()) {
            SettableBeanProperty prop = props.next();
            if (prop.getAnnotation(MyAnnotation.class) != null) {   
                builder.addOrReplaceProperty(prop.withValueDeserializer(new BadgerFishDeserializer()), true);
            }
        }
        return builder;
    }

}
公共类BadgerFishDeserializerModifier扩展了BeanDeserializerModifier{
@凌驾
公共BeanDeserializerBuilder更新生成器(反序列化配置、BeanDescription beanDesc、BeanDeserializerBuilder生成器){
迭代器props=builder.getProperties();
while(props.hasNext()){
SettableBeanProperty prop=props.next();
如果(prop.getAnnotation(MyAnnotation.class)!=null){
builder.addOrReplaceProperty(prop.withValueDeserializer(new-BadgerFishDeserializer()),true);
}
}
返回生成器;
}
}

这非常有用!最后,我不得不为String和XMLGregorianCalendar做一个特殊的反序列化程序。但问题并不止于此。BadgerFish从生成的类中获取@XMLAttributes,并将它们设置为@value而不是“value”。例如:

"BusinessRegisterEntityID": {
        "@register": "SE001",
        "$": "5568557184"
    }
那么,他们有没有办法将字段名自定义回原来的名称呢?现在我得到了这个异常:

Exception in thread "main" com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "@register" (class leigen.BusinessRegisterEntityIDType), not marked as ignorable (2 known properties: "value", "register"])
at [Source: (File); line: 44, column: 27] (through reference chain: java.lang.Object[][0]->leigen.LEIRecordType["Entity"]->leigen.EntityType["BusinessRegisterEntityID"]->leigen.BusinessRegisterEntityIDType["@register"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:60)
at com.fasterxml.jackson.databind.DeserializationContext.handleUnknownProperty(DeserializationContext.java:822)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1152)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1567)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1545)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:136)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:136)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:287)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890)
at Test.JSONParser.toJava(JSONParser.java:47)
at Test.JSONParser.main(JSONParser.java:28)
我可以通过在配置中放置一个“忽略”(UNKNOWN属性上的DeserializationFeature.FAIL_)来绕过这个问题,就像我现在的代码中一样:

    public static LEIRecordType[] toJava(File json) throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule();
    module.addDeserializer(String.class, new BadgerFishStringDeserializer());
    module.addDeserializer(XMLGregorianCalendar.class, new BadgerFishXMLGregorianCalendarDeserializer());
    module.addDeserializer(NameType.class, new BadgerFishNameTypeDeserializer());
    mapper.registerModule(module);
    mapper.registerModule(new JaxbAnnotationModule()); // To be able to read JAXB annotations.

    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(json, LEIRecordType[].class);
}   

但这仅将以@开头的值设置为null。还有别的办法解决这个问题吗?否则,我将不得不为所有生成的类编写一个自定义反序列化程序,大约25个(在下一个版本中可能会有更多)。我已经为NameType做了一个,但对于其他示例,还需要更多。

我认为清晰的解决方案是使用@JsonProperty(“$”):

实体类:

public class Entity {
   @JsonProperty("LegalName")
   private LegalName legalName;

   public LegalName getLegalName() {
       return legalName;
   }

   public void setLegalName(LegalName legalName) {
       this.legalName = legalName;
   }
}
LegalName类:

public class LegalName {
   @JsonProperty("$")
   private String value;

   public String getValue() {
       return value;
   }

   public void setValue(String value) {
       this.value = value;
   }
}

我希望您同时已经解决了这个问题,但以防万一:您可以在
寄存器
字段上使用
@JsonProperty(“@register”)
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
List<LEIModel> leiList = Arrays.asList(mapper.readValue(response.toString(), LEIModel[].class));
public class LEIModel {
   @JsonProperty("Entity")
   private Entity entity;

   public Entity getEntity() {
       return entity;
   }

   public void setEntity(Entity entity) {
       this.entity = entity;
   }
}
public class Entity {
   @JsonProperty("LegalName")
   private LegalName legalName;

   public LegalName getLegalName() {
       return legalName;
   }

   public void setLegalName(LegalName legalName) {
       this.legalName = legalName;
   }
}
public class LegalName {
   @JsonProperty("$")
   private String value;

   public String getValue() {
       return value;
   }

   public void setValue(String value) {
       this.value = value;
   }
}