gkiko
gkiko

Reputation: 2289

Simple framework. Do not serialize some variables to xml

I have problem serializing java object to XML. My classes are shown below:

@Root(strict = false, name = "Detail")
public class ProductList {
    @ElementList(inline = true, entry = "Product")
    private List<Product> products;
}

@Root(strict = false)
public class Product {
    @Element(name = "ProductCode")
    private String productCode;
    @Element(name = "ProductPrice")
    private double productPrice;
    @Element(name = "Currency")
    private String currency;
    @Element(name = "ConversionRate")
    private int conversionRate;
    @Element(name = "ProductPoints", required = false)
    private int productPoints;
    @Element(name = "ProductCount", required = false)
    private int productCount;
    @Element(name = "ProductName", required = false)
    private String productName;
    @Element(name = "MinPrice", required = false)
    private double minPricet;
    @Element(name = "MaxPrice", required = false)
    private double maxPricet;
    @Element(name = "CanChangePrice", required = false)
    private String canChangePrice;
}

The XML below is sent from server and it's deserialized without any problem:

<?xml version="1.0" encoding="UTF-8"?>
<Detail>
  <Product>
    <ProductCode>0001</ProductCode>
    <ProductPrice>0.90</ProductPrice>
    <Currency>GEL</Currency>
    <ConversionRate>200</ConversionRate>
    <ProductName>Bread</ProductName>
    <MinPrice>0.9</MinPrice>
    <MaxPrice>0.9</MaxPrice>
    <CanChangePrice>N</CanChangePrice>
  </Product>
  <Product>
    ...
  </Product>
</Detail>

I try to generate the XML document that will have this structure:

<?xml version="1.0" encoding="UTF-8"?>
<Detail>
  <Product>
    <ProductCode>0001</ProductCode>
    <ProductPrice>0.90</ProductPrice>
    <Currency>GEL</Currency>
    <ConversionRate>200</ConversionRate>
    <ProductPoints>180</ProductPoints>
    <ProductCount>1</ProductCount>
  </Product>
  <Product>
    ...
  </Product>
</Detail>

But I get this:

<Detail>
   <Product>
      <ProductCode>0001</ProductCode>
      <ProductPrice>0.9</ProductPrice>
      <Currency>GEL</Currency>
      <ConversionRate>200</ConversionRate>
      <productPoints>180</productPoints>
      <ProductCount>1</ProductCount>
      <ProductName>Bread</ProductName>
      <MinPrice>0.9</MinPrice>
      <MaxPrice>0.9</MaxPrice>
      <CanChangePrice>N</CanChangePrice>
   </Product>
   <Product>
      ...
   </Product>
</Detail>

Tags <ProductName>, <MinPrice>, <MaxPrice>, <CanChangePrice> mustn't be included in the serialized XML.

Is there any way I can tell the framework not to include specific tags\variables while serializing?

Upvotes: 2

Views: 1033

Answers (3)

Alexey Prudnikov
Alexey Prudnikov

Reputation: 1123

You can override default serialization mechanism with converter to customize the output. For example that you provide it will be:

public class CustomProductConverter implements Converter<Product> {

    private void createProductPropertyNode(OutputNode productNode, String propertyName, String value) throws Exception {
        productNode.getChild(propertyName).setValue(value);
    }

    private void createProductPropertyNode(OutputNode productNode, String propertyName, int value) throws Exception {
        createProductPropertyNode(productNode, propertyName, String.valueOf(value));
    }

    private void createProductPropertyNode(OutputNode productNode, String propertyName, double value) throws Exception {
        createProductPropertyNode(productNode, propertyName, String.valueOf(value));
    }

    @Override
    public Product read(InputNode inputNode) throws Exception {
        throw new UnsupportedOperationException();
    }

    @Override
    public void write(OutputNode outputNode, Product product) throws Exception {
        createProductPropertyNode(outputNode, "ProductCode"   , product.getProductCode());
        createProductPropertyNode(outputNode, "ProductPrice"  , product.getProductPrice());
        createProductPropertyNode(outputNode, "Currency"      , product.getCurrency());
        createProductPropertyNode(outputNode, "ConversionRate", product.getConversionRate());
        createProductPropertyNode(outputNode, "ProductPoints" , product.getProductPoints());
        createProductPropertyNode(outputNode, "ProductCount"  , product.getProductCount());

        outputNode.commit();
    }
}

And then use a RegistryStrategy for serialization:

Registry registry = new Registry();
registry.bind(Product.class, CustomProductConverter.class);

Strategy strategy = new RegistryStrategy(registry);
Serializer serializer = new Persister(strategy);

// serialize your object with serializer

PROS: you can dynamically serialize same object with different converters and get different output without modification of the model classes.

CONS: in the case of a complex model there will be a lot of similar code in converter.

Upvotes: 0

gkiko
gkiko

Reputation: 2289

My solution is pretty ugly. I created another class for XML serialization, that contains every field from the original class except the fields I wanted to omit in the XML.

Upvotes: 0

user1907906
user1907906

Reputation:

The problem

Your class members are not initialized to null and so required=false has not the effect of not serializing them.

ints are serialized by org.simpleframework.xml.transform.IntegerTransform. The write(Integer) method of this class is simple:

public String write(Integer value) {
   return value.toString();
}

As you can see, simple autoboxing is used.

  1. Your primitive int is initialized to 0 by the constructor.
  2. It is boxed into an Integer.
  3. The String value of this Integer is "0" which is not null.

Solution

Use Integer, not int for your class members.

Edit

If you don't want to serialize a member, don't annotate it with @Element. Simple is not about 'generating' XML but about mapping instances to/from XML. Every member you want to map needs an annotation. Every member with an annotation will be mapped.

Upvotes: 2

Related Questions