Index: /home/dejan/development/xstream/xstream/pom.xml =================================================================== --- /home/dejan/development/xstream/xstream/pom.xml (revision 1125) +++ /home/dejan/development/xstream/xstream/pom.xml (working copy) @@ -69,6 +69,12 @@ cglib-nodep true + + + org.codehaus.jettison + jettison + 1.0-RC1 + Index: /home/dejan/development/xstream/xstream/src/java/com/thoughtworks/xstream/io/jettison/JettisonDriver.java =================================================================== --- /home/dejan/development/xstream/xstream/src/java/com/thoughtworks/xstream/io/jettison/JettisonDriver.java (revision 0) +++ /home/dejan/development/xstream/xstream/src/java/com/thoughtworks/xstream/io/jettison/JettisonDriver.java (revision 0) @@ -0,0 +1,71 @@ +package com.thoughtworks.xstream.io.jettison; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.HashMap; + +import org.codehaus.jettison.mapped.MappedXMLInputFactory; +import org.codehaus.jettison.mapped.MappedXMLOutputFactory; + +import com.thoughtworks.xstream.io.HierarchicalStreamDriver; +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; +import com.thoughtworks.xstream.io.StreamException; +import com.thoughtworks.xstream.io.xml.QNameMap; +import com.thoughtworks.xstream.io.xml.StaxDriver; +import com.thoughtworks.xstream.io.xml.StaxReader; +import com.thoughtworks.xstream.io.xml.StaxWriter; + +/** + * Simple XStream driver wrapping Jettison's Mapped reader and writter. Serializes object from and to JSON. + * + * @author Dejan Bosanac + */ +public class JettisonDriver implements HierarchicalStreamDriver { + + StaxDriver driver = new StaxDriver(); + + MappedXMLOutputFactory mof; + MappedXMLInputFactory mif; + + public JettisonDriver() { + HashMap nstjsons = new HashMap(); + mof = new MappedXMLOutputFactory(nstjsons); + mif = new MappedXMLInputFactory(nstjsons); + } + + public HierarchicalStreamReader createReader(Reader reader) { + try { + return new StaxReader(new QNameMap(), mif.createXMLStreamReader(reader)); + } catch (Exception e) { + throw new StreamException(e); + } + } + + public HierarchicalStreamReader createReader(InputStream input) { + try { + return new StaxReader(new QNameMap(), mif.createXMLStreamReader(input)); + } catch (Exception e) { + throw new StreamException(e); + } + } + + public HierarchicalStreamWriter createWriter(Writer writer) { + try { + return new StaxWriter(new QNameMap(), mof.createXMLStreamWriter(writer)); + } catch (Exception e) { + throw new StreamException(e); + } + } + + public HierarchicalStreamWriter createWriter(OutputStream output) { + try { + return new StaxWriter(new QNameMap(), mof.createXMLStreamWriter(output)); + } catch (Exception e) { + throw new StreamException(e); + } + } + +} Index: /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/Category.java =================================================================== --- /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/Category.java (revision 0) +++ /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/Category.java (revision 0) @@ -0,0 +1,57 @@ +package com.thoughtworks.xstream.io.jettison; + +import java.util.List; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("category") +public class Category { + + String name; + String id; + List products; + + public Category(String name, String id) { + super(); + this.name = name; + this.id = id; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public List getProducts() { + return products; + } + + public void setProducts(List products) { + this.products = products; + } + + public String toString() { + String ret = "[" + name + ", " + id; + if (products != null) { + ret += "\n{"; + for (Product product : products) { + ret += product + "\n"; + } + ret += "}"; + } + ret += "]"; + return ret; + } + +} \ No newline at end of file Index: /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/JettisonDriverTest.java =================================================================== --- /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/JettisonDriverTest.java (revision 0) +++ /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/JettisonDriverTest.java (revision 0) @@ -0,0 +1,96 @@ +package com.thoughtworks.xstream.io.jettison; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.annotations.Annotations; + +/** + * Testing serialization to and from JSON with Jettison driver. + * + * @author Dejan Bosanac + */ +public class JettisonDriverTest extends TestCase { + + String simpleJson = "{\"com.thoughtworks.xstream.io.jettison.Product\":{\"name\":\"Banana\",\"id\":\"123\",\"price\":\"23.0\"}}"; + String annotationJson = "{\"category\":{\"name\":\"fruit\",\"id\":\"111\",\"products\":{\"product\":[{\"name\":\"Banana\",\"id\":\"123\",\"price\":\"23.0\"},{\"name\":\"Mango\",\"id\":\"124\",\"price\":\"34.0\"},{\"name\":\"Kiwi\",\"id\":\"125\",\"price\":\"46.0\"}]}}}"; + String hiearchyJson = "{\"category\":{\"name\":\"fruit\",\"id\":\"111\",\"products\":{\"product\":[{\"name\":\"Banana\",\"id\":\"123\",\"price\":\"23.0\",\"tags\":{\"string\":[\"yellow\",\"fresh\",\"tasty\"]}},{\"name\":\"Mango\",\"id\":\"124\",\"price\":\"34.0\"}]}}}"; + + public void testReadSimple() { + XStream xstream = new XStream(new JettisonDriver()); + Product product = (Product)xstream.fromXML(simpleJson); + assertEquals(product.getName(), "Banana"); + assertEquals(product.getId(), "123"); + assertEquals(product.getPrice(), 23.0); + } + + public void testWriteSimple() { + Product product = new Product("Banana", "123", 23.00); + XStream xstream = new XStream(new JettisonDriver()); + String result = xstream.toXML(product); + + assertEquals(result, simpleJson); + } + + public void testWriteAnnotations() { + Category category = new Category("fruit", "111"); + ArrayList products = new ArrayList(); + products.add(new Product("Banana", "123", 23.00)); + products.add(new Product("Mango", "124", 34.00)); + products.add(new Product("Kiwi", "125", 46.00)); + category.setProducts(products); + XStream xstream = new XStream(new JettisonDriver()); + Annotations.configureAliases(xstream, Category.class); + Annotations.configureAliases(xstream, Product.class); + String result = xstream.toXML(category); + assertEquals(result, annotationJson); + } + + public void testReadAnnotations() { + XStream xstream = new XStream(new JettisonDriver()); + Annotations.configureAliases(xstream, Category.class); + Annotations.configureAliases(xstream, Product.class); + Category category = (Category)xstream.fromXML(annotationJson); + assertEquals(category.getName(), "fruit"); + assertEquals(category.getProducts().size(), 3); + Product p = (Product)category.getProducts().get(1); + assertEquals(p.getName(), "Mango"); + } + + public void testWriteHierarchy() { + Category category = new Category("fruit", "111"); + ArrayList products = new ArrayList(); + Product banana = new Product("Banana", "123", 23.00); + ArrayList bananaTags = new ArrayList(); + bananaTags.add("yellow"); + bananaTags.add("fresh"); + bananaTags.add("tasty"); + banana.setTags(bananaTags); + products.add(banana); + Product mango = new Product("Mango", "124", 34.00); + products.add(mango); + category.setProducts(products); + XStream xstream = new XStream(new JettisonDriver()); + Annotations.configureAliases(xstream, Category.class); + Annotations.configureAliases(xstream, Product.class); + String result = xstream.toXML(category); + assertEquals(result, hiearchyJson); + } + + public void testHierarchyRead() { + XStream xstream = new XStream(new JettisonDriver()); + Annotations.configureAliases(xstream, Category.class); + Annotations.configureAliases(xstream, Product.class); + + Category parsedCategory = (Category)xstream.fromXML(hiearchyJson); + Product parsedBanana = (Product)parsedCategory.getProducts().get(0); + + assertEquals(parsedBanana.getName(), "Banana"); + assertEquals(parsedBanana.getTags().size(), 3); + assertEquals(parsedBanana.getTags().get(0), "yellow"); + assertEquals(parsedBanana.getTags().get(2), "tasty"); + } + +} \ No newline at end of file Index: /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/Product.java =================================================================== --- /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/Product.java (revision 0) +++ /home/dejan/development/xstream/xstream/src/test/com/thoughtworks/xstream/io/jettison/Product.java (revision 0) @@ -0,0 +1,78 @@ +package com.thoughtworks.xstream.io.jettison; + +import java.util.ArrayList; + +import com.thoughtworks.xstream.annotations.XStreamAlias; + +@XStreamAlias("product") +public class Product { + + String name; + String id; + double price; + ArrayList tags; + + + public Product(String name, String id, double price) { + super(); + this.name = name; + this.id = id; + this.price = price; + } + + + public String getId() { + return id; + } + + + public void setId(String id) { + this.id = id; + } + + + public String getName() { + return name; + } + + + public void setName(String name) { + this.name = name; + } + + + public double getPrice() { + return price; + } + + + public void setPrice(double price) { + this.price = price; + } + + + + public ArrayList getTags() { + return tags; + } + + + public void setTags(ArrayList tags) { + this.tags = tags; + } + + + public String toString() { + String ret = "[" + name + ", " + id + ", "+ price; + if (tags != null) { + ret += "\n{"; + for (String tag : tags) { + ret += tag + "\n"; + } + ret += "}"; + } + ret += "]"; + return ret; + } + +}