使用Jackson的Pojo挑剔的XML

发布于 2025-02-01 13:29:25 字数 1270 浏览 3 评论 0原文

Java 8,Spring 5.x

ResponseEntity<Object> responnse = restTemplate.exchange( myUrl, HttpMethod.GET, reqquest, Object.class);

定一些XML

<LinkedHashMap>
  <Entity>
    <name>Person</name>
    <href>../12345</href>
    <Attribute>
      <name>lastName</name>
      <type>String</type>
      <value>Nixon</value>
    </Attribute>
    <Attribute>
      <name>firstName</name>
      <type>String</type>
      <value>Dick</value>
     </Attribute>
   </Entity>
 </LinkedHashMap>

@JsonIgnoreProperties(ignoreUnknown=true)
@JacksonXmlRootElement(localName="Person")
@Entity
public class Person implements java.io.Serializable {

    private static final long serialVersionUID = 123456789L;

    @Id
    private Long id;
    private String lastName;
    private String firstName;
    ...
}

我如何将其调整到我可以的位置

if( responnse.hasBody()){
    Person person = xmlMapper.readValue( responnse.getBody(), Person.class);
    ...
}

,我认为XMLMLMAPPER至少需要一些自定义来处理ID。

蒂亚(Tia),

仍在努力的史蒂夫(Steve)

Java 8, Spring 5.x

Given

ResponseEntity<Object> responnse = restTemplate.exchange( myUrl, HttpMethod.GET, reqquest, Object.class);

returns some XML

<LinkedHashMap>
  <Entity>
    <name>Person</name>
    <href>../12345</href>
    <Attribute>
      <name>lastName</name>
      <type>String</type>
      <value>Nixon</value>
    </Attribute>
    <Attribute>
      <name>firstName</name>
      <type>String</type>
      <value>Dick</value>
     </Attribute>
   </Entity>
 </LinkedHashMap>

and

@JsonIgnoreProperties(ignoreUnknown=true)
@JacksonXmlRootElement(localName="Person")
@Entity
public class Person implements java.io.Serializable {

    private static final long serialVersionUID = 123456789L;

    @Id
    private Long id;
    private String lastName;
    private String firstName;
    ...
}

how do I adjust this to where I can

if( responnse.hasBody()){
    Person person = xmlMapper.readValue( responnse.getBody(), Person.class);
    ...
}

I'm think xmlMapper needs some customizing to handle the id, at the least.

TIA,

Still-struggling Steve

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

烦人精 2025-02-08 13:29:25

我不知道是否有优雅和一般的解决方案,但是您可以创建自定义的Deserializer,您可以在其中手动穿越XML并填充人类班级:

class PersonDeserializer extends StdDeserializer<Person> {

    protected PersonDeserializer() {
        super(Person.class);
    }

    @Override
    public Person deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Person result = new Person();
        do {
            String value = p.getText();

            if (value.equals("Attribute")) {
                p.nextToken(); // {
                p.nextToken(); // name
                p.nextToken(); // <attrName>

                String propertyName = p.getText();

                if (propertyName.equals("lastName")) {
                    p.nextToken(); // type
                    p.nextToken(); // String
                    p.nextToken(); // value
                    p.nextToken(); // <attrValue>
                    result.setLastName(p.getText());
                } else if (propertyName.equals("firstName")) {
                    p.nextToken(); // type
                    p.nextToken(); // String
                    p.nextToken(); // value
                    p.nextToken(); // value=<attrProperty>
                    result.setFirstName(p.getText());
                }
            } else if (value.equals("href")) {
                p.nextToken(); // value
                String href = p.getText();
                Long id = Long.parseLong(href.replaceAll("\\D", "")); // "../12345" => "12345"
                result.setId(id);
            }

            p.nextToken();

        } while (p.hasCurrentToken());

        return result;
    }
}

然后像这样的

XmlMapper mapper = new XmlMapper();
SimpleModule module = new SimpleModule("xmlPersonModule");
module.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(module);

String xml = """
        <LinkedHashMap>
          <Entity>
            <name>Person</name>
            <href>../12345</href>
            <Attribute>
              <name>lastName</name>
              <type>String</type>
              <value>Nixon</value>
            </Attribute>
            <Attribute>
              <name>firstName</name>
              <type>String</type>
              <value>Dick</value>
             </Attribute>
           </Entity>
         </LinkedHashMap>
        """;

Person person = mapper.readValue(xml, Person.class);
System.out.println(person);

输出一样致电:

人(id = 12345,lastName = nixon,firstName = dick)

ps 这是丑陋且不易于误解的解决方案,当给定XML结构更改时,它将失败,但...

I don't know if there is elegant and general solution, but you can create custom deserializer, where you manually traverse the XML and populate Person class:

class PersonDeserializer extends StdDeserializer<Person> {

    protected PersonDeserializer() {
        super(Person.class);
    }

    @Override
    public Person deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        Person result = new Person();
        do {
            String value = p.getText();

            if (value.equals("Attribute")) {
                p.nextToken(); // {
                p.nextToken(); // name
                p.nextToken(); // <attrName>

                String propertyName = p.getText();

                if (propertyName.equals("lastName")) {
                    p.nextToken(); // type
                    p.nextToken(); // String
                    p.nextToken(); // value
                    p.nextToken(); // <attrValue>
                    result.setLastName(p.getText());
                } else if (propertyName.equals("firstName")) {
                    p.nextToken(); // type
                    p.nextToken(); // String
                    p.nextToken(); // value
                    p.nextToken(); // value=<attrProperty>
                    result.setFirstName(p.getText());
                }
            } else if (value.equals("href")) {
                p.nextToken(); // value
                String href = p.getText();
                Long id = Long.parseLong(href.replaceAll("\\D", "")); // "../12345" => "12345"
                result.setId(id);
            }

            p.nextToken();

        } while (p.hasCurrentToken());

        return result;
    }
}

and then call like this

XmlMapper mapper = new XmlMapper();
SimpleModule module = new SimpleModule("xmlPersonModule");
module.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(module);

String xml = """
        <LinkedHashMap>
          <Entity>
            <name>Person</name>
            <href>../12345</href>
            <Attribute>
              <name>lastName</name>
              <type>String</type>
              <value>Nixon</value>
            </Attribute>
            <Attribute>
              <name>firstName</name>
              <type>String</type>
              <value>Dick</value>
             </Attribute>
           </Entity>
         </LinkedHashMap>
        """;

Person person = mapper.readValue(xml, Person.class);
System.out.println(person);

Output:

Person(id=12345, lastName=Nixon, firstName=Dick)

P.S. This is ugly and non-flexible solution, which will fail when given XML structure gets changed but... it just works :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文