Missing proper names during parsing java object to xml file

Kamil Wawer :

I want to return new .xml file with validated list base on source xml file. How to rewrite names of details in correct way, for account list using Jackson xmlMapper?

I want to read values from .xml file (Accounts details) and convert it into java objects. I need to group those single accountsnt into list. Than, I validate those accounts using some validators, and than I need to return checked account list to new xml file.

Name "LinkedList" shows, cause I use it in service class to rewrite list.

I give you my code below.

Can someone could help me?

Thanks!

Source XML file:

<accounts>
<account iban="PL61109010140000071219812875">
    <name>name1</name>
    <currency>PLN</currency>
    <balance>123.45</balance>
    <closingDate>2031-06-10</closingDate>
</account>
<account iban="PL61109010140000071219812871">
    <name>name2</name>
    <currency>PLN</currency>
    <balance>85.00</balance>
    <closingDate>2035-10-01</closingDate>
</account>
</accounts>

PARSER:

public class Parser {

private ObjectMapper objectMapper;

public Parser() {
    this.objectMapper = new XmlMapper();
}

public AccountList readFromXML() throws IOException {
    return objectMapper.readValue(
            readTextFromFile(), AccountList.class);
}

public void writeToXML(List<Account> account) throws IOException,     XMLStreamException {
    StringWriter stringWriter = new StringWriter();
    XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
    XMLStreamWriter sw = xmlOutputFactory.createXMLStreamWriter(stringWriter);

    XmlMapper mapper = new XmlMapper();
    objectMapper.writeValue(new
            File("src/main/resources/SortedData.xml"), account);
    sw.writeStartDocument();


}

private String readTextFromFile() throws IOException {

    InputStream in = new FileInputStream("src/main/resources/SourceData.xml");
    BufferedReader buff = new BufferedReader(new InputStreamReader(in));

    String line = buff.readLine();
    StringBuilder builder = new StringBuilder();

    while(line != null){
        builder.append(line).append("\n");
        line = buff.readLine(); }

    return builder.toString();
}
}

Account class:

public final class Account implements Serializable {

private static final long serialVersionUID = -4816735989159211337L;
@JacksonXmlProperty(localName = "iban", isAttribute = true)
private String accountIban;
@JacksonXmlProperty(localName = "name")
private String name;
@JacksonXmlProperty(localName = "currency")
private String currency;
@JacksonXmlProperty(localName = "balance")
private BigDecimal balance;
@JacksonXmlProperty(localName = "closingDate")
private String closingDate;

public Account() {
}

public Account(String accountIban, String name, String currency, BigDecimal balance, String closingDate) {
    this.accountIban = accountIban;
    this.name = name;
    this.currency = currency;
    this.balance = balance;
    this.closingDate = closingDate;
}

(I HAVE BASIC GETTERS AND SETTERS IN THS PLACE, BUT I DIDN'T PASE IT)   

@Override
public String toString() {
    return "Account{" +
            "accountNumber='" + accountIban + '\'' +
            ", name='" + name + '\'' +
            ", currency='" + currency + '\'' +
            ", balance=" + balance +
            ", closingDate=" + closingDate +
            '}';
}

@Override
public int hashCode() {
    return super.hashCode();
}

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Account account = (Account) o;
    return Objects.equals(accountIban, account.accountIban) &&
            Objects.equals(name, account.name) &&
            Objects.equals(currency, account.currency) &&
            Objects.equals(balance, account.balance) &&
            Objects.equals(closingDate, account.closingDate);
}
}

ACCOUNT LIST:

@JacksonXmlRootElement(localName = "accounts")
@XmlAccessorType(XmlAccessType.FIELD)
public final class AccountList implements Serializable {


private static final long serialVersionUID = 9215731280802778862L;

@JacksonXmlElementWrapper(localName = "accountList", useWrapping = false)
private List<Account> accountList;

public AccountList() {
}

GETTERS AND SETTERS IN THIS PLACE

@Override
public String toString() {
    return "Employees{" +
            "employees=" + accountList.toString() +
            '}';
}
}

SERVICE CLASS:

private AccountValidatorsImpl validators;

public AccountServiceImpl() {
    this.validators = new AccountValidatorsImpl();
}

@Override
public List<Account> validateEverySingleAccount(List<Account> sourceAccountList) {
    List<Account> validatedList = new LinkedList<>();
    for (Account account: sourceAccountList) {
        if(validators.checkAllValidators(account))
            validatedList.add(account);
    }
    return validatedList;
}

@Override
public List<Account> sortValidatedAccountList(List<Account> validatedAccountList){
    List<Account> sortedList = new LinkedList<>(validatedAccountList);

    Comparator<Account> comparator = (o1, o2) -> o1.getName().compareTo(o2.getName());

    sortedList.sort(comparator);
    return sortedList;
}
}

MAIN CLASS:

public static void main(String[] args) throws IOException, XMLStreamException {

    Parser parser = new Parser();
    AccountServiceImpl service = new AccountServiceImpl();
    AccountList list = parser.readFromXML();

    List<Account> listOfAccounts = list.getAccountList();
    List<Account> listOfValidatedAccounts = service.validateEverySingleAccount(listOfAccounts);
    List<Account> listOfSortedAccounts = service.sortValidatedAccountList(listOfValidatedAccounts);
    parser.writeToXML(listOfSortedAccounts);


OBJECT SERVICE IS CLASS WHERE I DO VALIDATION. IF IT WILL BE NESSECERY I   WILL PASTE IT

FINAL GENERATED XML FILE:

<LinkedList>
<item iban="PL61109010140000071219812875">
    <name>name1</name>
    <currency>PLN</currency>
    <balance>123.45</balance>
    <closingDate>2031-06-10</closingDate>
</item>
<item iban="PL61109010140000071219812871">
    <name>name2</name>
    <currency>PLN</currency>
    <balance>85.00</balance>
    <closingDate>2035-10-01</closingDate>
</item>
</LinkedList>

Unfortunately, during processing, program missing names, it is:loosing < accounts > and return < LinkedList > and < account > and give < item >. I need the same names for values.

Michał Ziober :

You forget to wrap List<Account> with AccountList. I fixed your Parser class which reads and writes XML using Jackson classes only. See below example:

import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        File inputFile = new File("./resource/test.xml").getAbsoluteFile();
        File outputFile = new File("./resource/output.xml").getAbsoluteFile();

        Parser parser = new Parser();
        List<Account> accounts = parser.readFromXML(inputFile).getAccountList();
        accounts.remove(0);
        parser.writeToXML(accounts, outputFile);
    }
}

class Parser {

    private XmlMapper xmlMapper;

    public Parser() {
        this.xmlMapper = new XmlMapper();
        this.xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
    }

    public AccountList readFromXML(File xmlFile) throws IOException {
        return xmlMapper.readValue(xmlFile, AccountList.class);
    }

    public void writeToXML(List<Account> accounts, File output) throws IOException {
        xmlMapper.writeValue(output, new AccountList(accounts));
    }
}

class Account implements Serializable {

    private static final long serialVersionUID = -4816735989159211337L;

    @JacksonXmlProperty(localName = "iban", isAttribute = true)
    private String accountIban;

    @JacksonXmlProperty(localName = "name")
    private String name;

    @JacksonXmlProperty(localName = "currency")
    private String currency;

    @JacksonXmlProperty(localName = "balance")
    private BigDecimal balance;

    @JacksonXmlProperty(localName = "closingDate")
    private String closingDate;

    public Account() {
    }

    public Account(String accountIban, String name, String currency, BigDecimal balance, String closingDate) {
        this.accountIban = accountIban;
        this.name = name;
        this.currency = currency;
        this.balance = balance;
        this.closingDate = closingDate;
    }

    // getters, setters, toString
}

@JacksonXmlRootElement(localName = "accounts")
class AccountList implements Serializable {

    private static final long serialVersionUID = 9215731280802778862L;

    @JacksonXmlProperty(localName = "account")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<Account> accountList;

    public AccountList() {
    }

    public AccountList(List<Account> accountList) {
        this.accountList = accountList;
    }

    // getters, setters, toString
}

Above code deserialises XML payload, removes 0-index item and writes rest of items to output.xml file which looks like this:

<accounts>
  <account iban="PL61109010140000071219812871">
    <name>name2</name>
    <currency>PLN</currency>
    <balance>85.00</balance>
    <closingDate>2035-10-01</closingDate>
  </account>
</accounts>

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=157377&siteId=1