Получение MismatchedInputException: Невозможно десериализовать экземпляр объекта при анализе JSON для получения результата объекта - PullRequest
0 голосов
/ 25 сентября 2019

Я хочу проанализировать файл XML со свойствами конфигурации в JSON и после этого привести этот JSON к объекту конечного результата.

Мой класс выглядит следующим образом:

@SpringBootApplication
public class AdvancedApplication {

  public static void main(String[] args) {

    SpringApplication.run(AdvancedApplication.class, args);

    XmlMapper xmlMapper = new XmlMapper();
    try {
      List XMLEntries = xmlMapper
          .readValue(new ClassPathResource("configuration.xml")
              .getFile(), List.class);

      ObjectMapper mapper = new ObjectMapper();
      String jsonConfig = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(XMLEntries);

      JsonNode parent = new ObjectMapper().readTree(jsonConfig);
      String content = parent.path("serverport").asText();

      System.out.println(content);

      System.out.println(jsonConfig);
    } catch (IOException e) {
      e.printStackTrace();
    }

  }

}

В первом сценарии:

List XMLEntries = xmlMapper
          .readValue(new ClassPathResource("configuration.xml")
              .getFile(), List.class);

При описанном выше подходе JSON включается в список с таким результатом:

[ {
  "serverport" : "9966"
}, {
  "clientport" : "9999",
  "serverHost" : "localhost"
} ]

но в этом случае я не могу прочитать значение в строке:

String content = parent.path("serverport").asText();

, потому что содержимое пусто.

Наконец, я решил привести JSON к результирующему объекту Config следующим образом:

Config configObject = mapper.readValue(jsonConfig, Config.class);

, но, к сожалению, я получаю исключение типа:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.javase.advanced.config.Config` out of START_ARRAY token
 at [Source: (String)"[ {
  "serverport" : "9966"
}, {
  "clientport" : "9999",
  "serverHost" : "localhost"
} ]"; line: 1, column: 1]

Мой файл configuration.xml выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <server serverport="9966"/>
  <client clientport="9999">
    <serverHost>localhost</serverHost>
  </client>
</config>

И класс конфигурации выглядит следующим образом:

@NoArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public class Config {

  private Server server;
  private Client client;
}

Server.class

@AllArgsConstructor
@Getter
@NoArgsConstructor
public class Server {

  @JsonProperty("serverport")
  private String serverPort;

}

Config.class

@Getter
@NoArgsConstructor
public class Client {

  @JsonProperty("serverHost")
  private String serverHost;

  @JsonProperty("clientport")
  private String clientPort;
}

Все, чего я хочу добиться, - это разбор файла configuration.xml в JSON и приведение его к объекту Config для создания класса конфигурации для дальнейшего использования.

РЕДАКТИРОВАТЬ:

После предложения @pvpkiran я попробовал подход как:

      Config configValue = xmlMapper.readValue(new ClassPathResource("configuration.xml")
          .getFile(), Config.class);

, но в конце концов я получаю сообщение об ошибке типа:

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "serverport" (Class com.javase.advanced.server.Server), not marked as ignorable
 at [Source: C:\Users\mzawadzki\Desktop\advanced\target\classes\configuration.xml; line: 3, column: 30] (through reference chain: com.javase.advanced.config.Config["server"]->com.javase.advanced.server.Server["serverport"])

EDIT2:

После модификации мои классы выглядят так:

Client.class

@Getter
@NoArgsConstructor
public class Client {

  @JacksonXmlProperty(localName = "clientport")
  private String clientPort;
  @JacksonXmlProperty(localName = "serverHost")
  private String serverHost;

}

Server.class

@AllArgsConstructor
@Getter
@NoArgsConstructor
public class Server {
  @JacksonXmlProperty(localName = "serverport")
  private String serverPort;
}

Я создалОбертка для моего класса конфигурации, как избавиться от [ и ] вхождения.

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@JacksonXmlRootElement(localName = "config")
public class ConfigWrapper {
  private Config[] configurations;
}

Теперь мой класс конфигурации выглядит следующим образом:

@NoArgsConstructor
@Getter
@AllArgsConstructor
@ToString
public class Config {

  @JacksonXmlProperty(localName = "serverport")
  private Server server;
  @JacksonXmlProperty(localName = "client")
  private Client client;
}

, но опять же это не решило проблему, и в конце концов я получаю исключение:

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "server" (Class com.javase.advanced.config.ConfigWrapper), not marked as ignorable
 at [Source: (through reference chain: com.javase.advanced.config.ConfigWrapper["server"])

Буду благодарен за предложение о том, как достичь цели и избавиться от этого исключения.

Ответы [ 2 ]

1 голос
/ 25 сентября 2019

Это должно работать.Вы можете использовать JAXB для демаршаллинга.Читайте про JAXB.Также обратите внимание на то, как используются XmlElement и XmlAttribute.

String xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<config>\n" +
                "  <server serverport=\"9966\"/>\n" +
                "  <client clientport=\"9999\">\n" +
                "    <serverHost>localhost</serverHost>\n" +
                "  </client>\n" +
                "</config>";

JAXBContext jaxbContext;
 try
   {
      jaxbContext = JAXBContext.newInstance(Config.class);
      Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
      Config config = (Config) jaxbUnmarshaller.unmarshal(new StringReader(xmlString));
      System.out.println(config);
   }catch (JAXBException e){
      e.printStackTrace();
  }

Класс конфигурации будет таким

@XmlRootElement(name = "config")
@XmlAccessorType(XmlAccessType.PROPERTY)
public class Config {
    public Server server;
    public Client client;

    public Config() {
    }

    public Server getServer() {
        return server;
    }

    public void setServer(Server server) {
        this.server = server;
    }

    public Client getClient() {
        return client;
    }

    public void setClient(Client client) {
        this.client = client;
    }
}

Класс сервера

public class Server {
    @XmlAttribute(name = "serverport")
    public String serverPort;
}

Клиенткласс

public class Client {

    @XmlAttribute(name = "clientport")
    public String clientPort;

    @XmlElement
    public String serverHost;
}
0 голосов
/ 26 сентября 2019

Решение pvpkiran решило проблему, но я не мог смириться с тем фактом, что Джексон не смог проанализировать XML для одного объекта.Расследование приносит желаемый эффект, и в итоге выяснилось, что в моем pom.XML есть две схожие зависимости, такие как jackson-databind и jackson-xml-databind.Оказывается, между ними существует конфликт.После комментария jackson-xml-databind все работает отлично.

Теперь мои занятия выглядят следующим образом:

Client.class

@Getter
@NoArgsConstructor
@Setter
public class Client {

  @JacksonXmlProperty(localName = "clientport")
  private String clientPort;
  @JacksonXmlProperty(localName = "serverHost")
  private String serverHost;

}

Server.class

@AllArgsConstructor
@Getter
@NoArgsConstructor
@Setter
public class Server {
  @JacksonXmlProperty(localName = "serverport")
  private String serverPort;
}

Config.class

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
@JacksonXmlRootElement(localName = "config")
public class Config {

  private Server server;
  private Client client;
}

Еще раз спасибо за обязательство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...