Coder Social home page Coder Social logo

gson-xml's Introduction

GsonXml

GsonXml is a small library that allows using [Google Gson library] (https://code.google.com/p/google-gson/) for XML deserialization. The main idea is to convert a stream of XML pull parser events to a stream of JSON tokens. It's implemented by passing a custom JsonReader (that wraps XmlPullParsers) to Gson.

Though currently this library is not pretending to be the most efficient one for XML deserialization, it can be very useful.

Build Status

Compatible Gson versions: 2.1, 2.2.

Usage

/** Very simple model. */
public static class SimpleModel {
  private String name;
  private String description;

  public String getName() { return name; }
  public String getDescription() { return description; }
}


public void simpleTest() {
  
  XmlParserCreator parserCreator = new XmlParserCreator() {
    @Override
    public XmlPullParser createParser() {
      try {
        return XmlPullParserFactory.newInstance().newPullParser();
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }
  };

  GsonXml gsonXml = new GsonXmlBuilder()
     .setXmlParserCreator(parserCreator)
     .create();

  String xml = "<model><name>my name</name><description>my description</description></model>";
  SimpleModel model = gsonXml.fromXml(xml, SimpleModel.class);
  
  assertEquals("my name", model.getName());
  assertEquals("my description", model.getDescription());
}

Use @SerializedName annotation to handle tag attributes and text nodes.

To illustrate, this XML

<person dob="01.01.1973" gender="male">
  <name>John</name>
  Likes traveling.
</person>

can be mapped to a POJO

public class Person {

  @SerializedName("@dob")
  private String dob;

  @SerializedName("@gender")
  private String gender;

  private String name;

  @SerializedName("$")
  private String description;

  // ...
}

You may also take a look at SimpleXmlReaderTest to see other samples.

Deserializing lists

Since there is no direct analogy of JSON arrays in XML, some ambiguity appears when you are trying to deserialize lists. GsonXmlBuilder has method setSameNameLists(boolean) in order to resolve this issue.

Considering the following Java class

class Container {
  List<Person> persons;
}

Call setSameNameLists(false) in order to deserialize such an object from the following XML:

<container>
  <persons>
    <any-tag-name id="1">
      <name>John</name>
    </any-tag-name>
    <any-tag-name id="2">
      <name>Mark</name>
    </any-tag-name>
  </persons>
</container>

Note that tag names of persons tag children nodes are ignored.

And call setSameNameLists(true) in order to deserialize such an object from another piece of XML:

<container>
  <person id="1">
    <name>John</name>
  </person>
  <person id="2">
    <name>Mark</name>
  </person>
</container>

Don't forget to put SerializedName('person') annotation on persons field.

Note that at the moment it's impossible to deserialize more than one list in the same container with option setSameNameLists(true).

Also be aware that currently it's impossible to deserialize XML structure where both types of lists exist.

Download

In a Maven project include the dependency:

<dependency>
  <groupId>com.stanfy</groupId>
  <artifactId>gson-xml-java</artifactId>
  <version>(insert latest version)</version>
</dependency>

Gradle example:

compile 'com.stanfy:gson-xml-java:0.1.+'

Android Notes

In order to use this library in Android project, copy only gson-xml and gson jars to the project libraries folder. kxml2 and xmlpull jars are not required since XmlPullParser is a part of Android SDK. To exclude them in your Gradle project use the following lines:

compile('com.stanfy:gson-xml-java:0.1.+') {
  exclude group: 'xmlpull', module: 'xmlpull'
}

Also be aware that Android SDK up to 'Ice Cream Sandwich' returns instance of ExpatPullParser when you call Xml.newPullParser(). And this parser does not support namespaces.

Read also this blog post about issues with Android XML parsers.

License

Copyright 2013 Stanfy Corp.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

gson-xml's People

Contributors

atyschenko avatar gaul avatar roman-mazur avatar seanhussey avatar stanfy-integrator avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gson-xml's Issues

Deserializing with setSameNameLists(true) fails with JsonSyntaxException

Consider the following test case:

  private static final String TEST_ACL_XML =
    "<Class1>" +
    "    <Class2>" +
    "        <Class3/>" +
    "    </Class2>" +
    "</Class1>";

  @Test
  public void testAclXml() {
    Class1 acl = new GsonXmlBuilder()
        .setXmlParserCreator(SimpleXmlReaderTest.PARSER_CREATOR)
        .setSameNameLists(true)
        .create()
        .fromXml(TEST_ACL_XML, Class1.class);
  }

  static final class Class1 { 
    @SerializedName("Class2")
    List<Class2> class2;

    static final class Class2 { 
      @SerializedName("Class3")
      Class3 class3;

      static final class Class3 {
      }
    }
  }

which fails with:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met STRING
Scopes: INSIDE_OBJECT>NAME>INSIDE_OBJECT>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT
Closed tags: 'Class3'/3
Token: null
Tokens queue: null
Values queue: , null

    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.Gson.fromJson(Gson.java:795)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:96)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:66)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:52)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:42)
    at com.stanfy.gsonxml.test.ListsTest.testAclXml(ListsTest.java:303)

Removing setSameNameLists(true) allows the test to pass although my application requires this behavior.

Array deserealization

Hi,

I'm trying to convert xml to json using your library. I wrote following code:

String xml = "<root><list><item>1</item><item>2</item></list></root>";
String json = Serializer.toJson(xml);

and expecting to see json similar to: { list: [ {"item":1}, {"item":2}]}

toJson method has following code:
StringReader stringReader = new StringReader(xml);

//options are skipRoot only
XmlReader xmlReader = new XmlReader(stringReader, getXmlParserCreator(), getOptions());

//standard GSON parser
JsonParser p = new JsonParser();
JsonElement element = p.parse(xmlReader);
return element.toString();

but instead of array I received followign json:
{"list":{"item":"2"}}

with the last array item only.

I understand that it is a little bit tricky usage of your library, but maybe you will advise something to me?

Thank you!

Deserializing error

Hello,

In case when the markup parameter is optional there could be happen deserializing error:

  Caused by: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met STRING
    Scopes: INSIDE_OBJECT>NAME>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT
    Closed tags: 'programme'/2>'previously-shown'/3
    Token: null
    Tokens queue: null
    Values queue: , null

The markup might look like:

<previously-shown start="20080306000000" />

or

<previously-shown  />

My container class looks like:

public class PreviouslyShown {

    @SerializedName("@start")
    Date start;
}

Is it bug or there is any option to deserialize this markup?

How should I model this?

From a website I receive this XML.
Note that the tag Location is twice. How should I moel the POJOs for this XML?

Bahia Blanca (CONICET) Populated place Argentina

Thanks!

BEGIN_OBJECT expected, but met STRING Scopes: INSIDE_OBJECT>NAME>INSIDE_OBJECT>INSIDE_ARRAY>INSIDE_OBJECT

Hello. Please, help me.
I have next xml variants.

Variant 1

<?xml version="1.0"?>
<main>
  <array_data>
    <element>
      <tag>first</tag>
      <thumbnail_hq>
        <hundred_fifty_square>55/55271.jpg</hundred_fifty_square>
        <three_hundred_square>55271.jpg</three_hundred_square>
      </thumbnail_hq>
    </element>
    <element>
      <tag>second</tag>
      <thumbnail_hq>
        <hundred_fifty_square>55/55277861.jpg</hundred_fifty_square>
        <three_hundred_square>55276871.jpg</three_hundred_square>
      </thumbnail_hq>
    </element>
  </array_data>
</main>

Variant 2

<?xml version="1.0"?>
<main>
  <array_data>
    <element>
      <tag>first</tag>
      <thumbnail_hq>
        <hundred_fifty_square>55/55271.jpg</hundred_fifty_square>
        <three_hundred_square>55271.jpg</three_hundred_square>
      </thumbnail_hq>
    </element>
    <element>
      <tag>second</tag>
      <thumbnail_hq/>
    </element>
  </array_data>
</main>

When I parse 1 variant - all good. But, when I try to parse 2 variant - I receive error:

Caused by: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met STRING
        Scopes: INSIDE_OBJECT>NAME>INSIDE_OBJECT>INSIDE_ARRAY>INSIDE_OBJECT
        Closed tags:
        Token: null
        Tokens queue: null
        Values queue: , null
        at com.stanfy.gsonxml.XmlReader.expect(XmlReader.java:143)
        at com.stanfy.gsonxml.XmlReader.beginObject(XmlReader.java:149)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:165)
        ... 25 more

I can not work with an empty element.

This my POJO class.

public class Element implements Serializable {

  private static final long serialVersionUID = 4286550870315187343L;

  @SerializedName("tag")
  private String tag;

  @SerializedName("thumbnail_hq")
  private Thumb thumbnail_hq;
}
public class Thumb implements Serializable {

  private static final long serialVersionUID = 4286550870315187343L;

  @SerializedName("hundred_fifty_square")
  private String hundred_fifty_square;

  @SerializedName("three_hundred_square")
  private String three_hundred_square;
}

ArrayIndexOutOfBoundsException when parsing XML

Thank you for your work with this tool!

I think I found a bug: I get an ArrayIndexOutOfBoundsException when I parse XML.

I have the following XML structure:

    String xml = "<one date=\"1376576721\">"
            + "<two id=\"11\">"
            + "<three id=\"5\" title=\"test\">"
            + "</three>"
            + "</two>"
            + "</one>";

One can contain multiple twos, and two can contain multiple threes.

I have the classes according this:

public class One {

    @SerializedName("@date")
    private long date;

    @SerializedName("two")
    private List<Two> twos;
}

public class Two {

    @SerializedName("@id")
    private int id;

    @SerializedName("three")
    private List<Three> threes;
}

public class Three {

    @SerializedName("@id")
    private int id;

    @SerializedName("@title")
    private String title;
}

I set builder.setSameNameLists(true).

But then I get an error:

Caused by: java.lang.ArrayIndexOutOfBoundsException: length=32; index=-1
    at com.stanfy.gsonxml.XmlReader.processEnd(XmlReader.java:601)
    at com.stanfy.gsonxml.XmlReader.fillQueues(XmlReader.java:470)
    at com.stanfy.gsonxml.XmlReader.peek(XmlReader.java:293)
    at com.stanfy.gsonxml.XmlReader.hasNext(XmlReader.java:163)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:80)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:92)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:66)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:52)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:42)

Thank you for your help in advance!

Self-closing tag, xml to pojo fail

Hi , I tried to convert xml to a java object
if I put a self-closing tag like < attribute />
the converter went wrong.
is this supported in gson-xml ?
thanks !

GsonXml with setSameNameLists(true) deserializes incorrectly to a POJO with multiple list fields

When trying to deserialize to a POJO with multiple list fields of different types, using setSameNameLists(true), some elements fail to be included in the result.

System:
Windows 7 64-bit SP1
Java 1.7.0_25 32-bit
gson-2.2.4
gson-xml-0.1.6
xpp3-1.1.3.4.C

import java.math.BigDecimal;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import com.google.gson.annotations.SerializedName;
import com.stanfy.gsonxml.GsonXml;
import com.stanfy.gsonxml.GsonXmlBuilder;
import com.stanfy.gsonxml.XmlParserCreator;

public class GsonXmlTest {
    public static void main(String[] args) {
        XmlParserCreator parserCreator = new XmlParserCreator() {
            public XmlPullParser createParser() {
                try {
                    return XmlPullParserFactory.newInstance().newPullParser();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        };

        GsonXml gsonXml = new GsonXmlBuilder()
                .setSameNameLists(true)
                .setXmlParserCreator(parserCreator)
                .create();

        A a = gsonXml.fromXml("<A><B value=\"23.5\" /><C>Test</C></A>", A.class);
        System.out.println(gsonXml.getGson().toJson(a));
    }

    static class A {
        List<B> B;
        List<C> C;
    }

    static class B {
        @SerializedName("@value")
        BigDecimal  value;
    }

    static class C {
        @SerializedName("$")
        String  text;
    }
}

Expected output:

{"B":[{"@value":23.5}],"C":[{"$":"Test"}]}

Actual output:

{"B":[{"@value":23.5},{}]}

Unable to parse array located at 3rd level of nested xml com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met NAME

# Can't parse <subject> node data. Its giving following error,

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met NAME
Scopes: INSIDE_OBJECT>NAME>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT>NAME>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT>NAME>INSIDE_OBJECT
Closed tags: 'semester'/3
Token: null
Tokens queue: BEGIN_OBJECT, NAME, STRING, NAME, STRING, NAME, STRING, null
Values queue: semester, @semno, 2, @min_crd_req, 22, @cum_crd_req, 48, null

POJOs

public class specialisations {    
    @SerializedName("specialisation")
    private List<specialisation> specialisationList;
}

public class specialisation {
    @SerializedName("@dept")
    private String dept = "";
    @SerializedName("@coursecode")
    private String coursecode = "";
    @SerializedName("@coursename")
    private String coursename = "";
    @SerializedName("semester")
    private List<semester> semester;
}

public class semester {    
    @SerializedName("@semno")
    private String semno="";    
    @SerializedName("@min_crd_req")
    private String min_crd_req="";    
    @SerializedName("@cum_crd_req")
    private String cum_crd_req="";    
    @SerializedName("subject")
    private List<subject> subject;
}

public class subject {    
    @SerializedName("subno")
    private String subno="";    
    @SerializedName("subname")
    private String subname="";    
    @SerializedName("ltp")
    private String ltp="";    
    @SerializedName("crd")
    private String crd="";    
    @SerializedName("sub_type")
    private String sub_type="";
}

XML DATA :-

<specialisations>
        <specialisation dept="AT" coursecode="AT1" coursename="EMBEDDED">
                  <semester semno="1"  min_crd_req="26" cum_crd_req="26">
                             <subject>
                                      <subno>1</subno>
                                      <subname>A</subname>
                                      <ltp>1-1</ltp>
                                      <crd>12</crd>
                                      <sub_type>C</sub_type>
                             </subject>
                             <subject>
                              .....same as above........
                             </subject>
                             <subject>
                              .....same as above........
                             </subject>
                  </semester>
                  <semester semno="2"  min_crd_req="26" cum_crd_req="26">
                        .....same as above........
                  </semester>
        </specialisation>

        <specialisation dept="BT" coursecode="BT" coursename="BT">
              .....same as above........
        </specialisation>

        <specialisation dept="CT" coursecode="CT" coursename="CT">
              .....same as above........
        </specialisation>

        <specialisation dept="DT" coursecode="DT" coursename="DT">
              .....same as above........
        </specialisation>

</specialisations>

See error details, POJOs and XML content here :
https://drive.google.com/open?id=1Afj66c5ocjpd6E9lK3bJYg_R8XeQzPQlRRpkXJW7BMU

How to deserialize duplicate tags

Hello, please help me. Can I deserialize such xml:

<?xml version="1.1" encoding="UTF-8" ?>
<important_information>
<category>Information</category>
<title>Description</title>
<paragraph>Paragraph</paragraph>
<category>Room</category>
<title>Cancellation</title>
<paragraph>Next</paragraph>
<title>Guarantee</title>
<paragraph>Such</paragraph>
<title>Cancellation</title>
<paragraph>Hello</paragraph>
<title>Service</title>
<paragraph>Customer</paragraph>
</important_information>

Enable to parse primitive list with same names when param exist in the root tag

I was plaing aroung with your api and I found that :

ListsTest

@Test
  public void primitiveListIntSameName() {
    String xml = "<response name=\"test\">"
          + "  <item>1</item>"
          + "  <item>2</item>"
          + "  <item>3</item>"
          + "</response>";

    final List<Integer> intList =
        new GsonXmlBuilder()
        .setXmlParserCreator(parserCreator)
        .setSkipRoot(true)
        .setRootArrayPrimitive(true)
        .create()
        .fromXml(xml, new TypeToken<List<Integer>>() { }.getType());
    assertEquals(3, intList.size());
    assertEquals(3, (int)intList.get(2));
  }

Is this normal situation or it is a bug?

support android xml binary resource

Android compile xml file resource to binary to reduce size and improve performance

GsonXml can add static method, so GsonXml avoid to call XmlPullParser::setInput to prepare the input data

public <T> T fromXml(final XmlPullParser parser, final Class<T> classOfT){
    ................................
}

user can call this method like below code
gsonXml.fromXml(getContext().getResources().getXml(R.xml.config), clazz)

need advice

hi. very good lib! save my day or more :)
so i have question:

have XML:

<root>
  <sub>
    <ssub>.....</ssub>
   </sub>
</root>

for deserialize i have made custom class in class (ssub in sub)
but i don`t need SUB to deserialize (realy need result like root -> ssub)
can i notice source to deserialize in that behaviour?

Deserializing an array

Hello,

I am trying to deserialize an XML array as returned by this query:

http://www.musicbrainz.org/ws/2/recording/?query=Entracte~%20AND%20artist:The%20Cinema%20Orchestra~

And while I am able to properly decode "recording-list" "count" and "offset" using this:

@SerializedName("@count")
int count;

@SerializedName("@offset")
int offset;

but adding following to decode all "recording" tags

XMBRecording[] recording;

causes this:

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: NAME expected, but met STRING
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
at com.google.gson.internal.bind.ArrayTypeAdapter.read(ArrayTypeAdapter.java:72)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
at com.google.gson.Gson.fromJson(Gson.java:795)
at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:92)
at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:66)
at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:52)
at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:42)
at pl.qus.xenoamp.helper.Jxml.Deserialize(Jxml.java:28)
at pl.qus.musicbrainz.MBParser.test(MBParser.java:181)
at pl.qus.xenoamp.XenoAmp$Testowy.run(XenoAmp.java:162)
at java.lang.Thread.run(Thread.java:856)
Caused by: java.lang.IllegalStateException: NAME expected, but met STRING
at com.stanfy.gsonxml.XmlReader.expect(XmlReader.java:137)
at com.stanfy.gsonxml.XmlReader.nextName(XmlReader.java:338)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:167)
... 15 more

Am I doing something wrong or are arrays just not supported?

BEGIN_OBJECT expected, but met NAME

Hi.

I'm having an issue while parsing an XML api response.

It's similar to this issue, but I can't change the XML like he did.

What am I doing wrong ?

My Error:

Process: myproject.com, PID: 26672
    com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met NAME
    Scopes: INSIDE_OBJECT>NAME>INSIDE_OBJECT>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT>NAME
    Closed tags: 'person'/2
    Token: null
    Tokens queue: null
    Values queue: person, null

My XML:

<website>
    <person>
        <id_person>60</id_person>
        <name>Peter</name>
        <personal_items>
            <item>
                <id>165</id>
                <name>Phone</name>
            </item>
            <item>
             ...
            </item>
        </personal_items>
    </person>
    <person>
	...
	</person>
</website>

My Model:

public class Persons {
    private List<Person> person;	
	//getters
}
public class Person {
	String id_preson;
	String name;
	PersonalItems personal_items;
	//getters
}
public class PersonalItems{
	List<Item> item;
	//getters
}
public class Item{
	String id;
	String name;
	//getters
}

My Java code:

XmlParserCreator parserCreator = new XmlParserCreator() {
                @Override
                public XmlPullParser createParser() {
                    try {
                        return XmlPullParserFactory.newInstance().newPullParser();
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            };
GsonXml gsonXml = new GsonXmlBuilder()
                    .setXmlParserCreator(parserCreator)
                    .setSameNameLists(true)
                    .create();
					
Persons persons = gsonXml.fromXml(xml, Persons.class);

Cannot deserialize elements with optional attributes

I have an xml document that has elements with values and optional attributes. For example:

<root>
<SomeElement version="2.0">StringValue</SomeElement>
</root>

In the above scenario, I cannot deserialize the value as a String, since the parser is expecting an object due to the presence of the "version" attribute. I then created a class like this:

class Root
{
    @SerializedName("SomeElement")
    public SomeElement someElement;
}
...
class SomeElement
{
    @SerializedName("$")
    public String value;
}

This works until I encounter a "SomeElement" that has the "version" attribute omitted. At that point, the parser attempts to read the value as a String while Gson is of course still expecting an object due to the above object model.

Is there an easy way out of this situation? Cheers.

GsonXml with setSameNameLists(true) throws exception when deserializing empty list nodes

When trying to deserialize to a POJO with with a list field, using setSameNameLists(true), there are "empty" XML elements for the list, GsonXml throws an exception.

System:
Windows 7 64-bit SP1
Java 1.7.0_25 32-bit
gson-2.2.4
gson-xml-0.1.6
xpp3-1.1.3.4.C

import java.math.BigDecimal;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import com.google.gson.annotations.SerializedName;
import com.stanfy.gsonxml.GsonXml;
import com.stanfy.gsonxml.GsonXmlBuilder;
import com.stanfy.gsonxml.XmlParserCreator;

public class GsonXmlTest {
    public static void main(String[] args) {
        XmlParserCreator parserCreator = new XmlParserCreator() {
            public XmlPullParser createParser() {
                try {
                    return XmlPullParserFactory.newInstance().newPullParser();
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        };

        GsonXml gsonXml = new GsonXmlBuilder()
                .setSameNameLists(true)
                .setXmlParserCreator(parserCreator)
                .create();

        A a = gsonXml.fromXml("<A><B /></A>", A.class);
        System.out.println(gsonXml.getGson().toJson(a));
    }

    static class A {
        List<B> B;
    }

    static class B {
        @SerializedName("@value")
        BigDecimal  value;
    }
}

Expected output:

{"B":[{}]}

Actual output:

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met STRING
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:176)
    at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.read(TypeAdapterRuntimeTypeWrapper.java:40)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:81)
    at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.read(CollectionTypeAdapterFactory.java:60)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172)
    at com.google.gson.Gson.fromJson(Gson.java:803)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:92)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:66)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:52)
    at com.stanfy.gsonxml.GsonXml.fromXml(GsonXml.java:42)
    at com.cybertrader.master.message.fixml2.GsonXmlTest.main(GsonXmlTest.java:31)
Caused by: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met STRING
    at com.stanfy.gsonxml.XmlReader.expect(XmlReader.java:137)
    at com.stanfy.gsonxml.XmlReader.beginObject(XmlReader.java:143)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:165)
    ... 11 more

com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: BEGIN_OBJECT expected, but met STRING

Scopes: INSIDE_OBJECT>NAME>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT>NAME>INSIDE_OBJECT>NAME>INSIDE_OBJECT>NAME>INSIDE_EMBEDDED_ARRAY>INSIDE_OBJECT>NAME>INSIDE_OBJECT
Closed tags: 'Impression'/4>'TrackingEvents'/7
Token: null
Tokens queue: null
Values queue: , null

Getting above error for this XML. https://github.com/rs/vast/blob/master/testdata/vast_wrapper_linear_2.xml

Error is for empty

"<TrackingEvents> </TrackingEvents>"

tags. Any suggestions for this?

Removes &amp; from URLs

I'm trying to parse Accuweather api data that's in xml, and there are a few links in the data they return that contain escape ampersands. When I parse the xml the '&' are hacked off the URLs and replaced with a space.

Do not use "$" for text nodes

When you want to get the text node of an element you can use the @SerializedName( "$" ) annotation which is pretty nice. Anyway, there are some problems with the "$".

Converting xml to objects works fine with this approach. But if you want to do a serialization back as json with plain Gson you may ran into problems. The field gets serialized with the name "$" because Gson also respects the @SerializedName annotation. This causes huge problems if you want to store the serialized object into databases e.g. MongoDB forbids to start keys with "$".

So, replacing the "$" would break API and is not an option I think. But would it be possible to make it configurable? By taking a first look at the code this should be doable, right?

GsonXml class cannot be mocked

The class is marked as final which prevents mocking in unit tests. Please remove the final keyword from the class declaration.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.