user320550
user320550

Reputation: 1175

converting json into java object for a array with mixed types

My json string looks like the following:

{
  "text": ["foo",1,"bar","2",3],
  "text1": "value1",
  "ComplexObject": {
   .....
   }
}

I have a pojo defined like this:

class MyPojo {
 List<String> text;
 String text1;
 ComplexObject complexObject;
}

I use google gson and am able to get my java object populated properly. The problem here is that the field text is an array of mixed types (string and int). So all the entries there are converted into String and i am not able to figure out which entries in the array is a string vs int. I cant use parseInt since the entries in the original array may have "2" as well as 3.

Is there a way for me to get the right instance type of the fields in my array after converting into java object.

SOLUTION

So i implemented the solution using gson the round about way using the JsonDeserializer. And then i tried using jackson. Guess what jackson supports serializing/deserializing the mixed array type by preserving the data types.

ObjectMapper mapper = new ObjectMapper();
MyPojo gmEntry = mapper.readValue(json, new TypeReference<MyPojo >(){});

And i can basically fetch the List<Object> and do an instanceof to check for the datatype.

Shame on you gson!!

Upvotes: 3

Views: 5610

Answers (5)

SomeStudent
SomeStudent

Reputation: 3048

Not sure if this is what you need, but this is the code I use for parsing JSON.

static public void newsParser(String urlString, String targetObject) throws FileNotFoundException, IOException
    {

        URL url = new URL(urlString);

        JSONParser parser=new JSONParser();


           BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));



           Object obj;
        try 
        {
            obj = parser.parse(br);         
            //JSONObject jsonObject = (JSONObject) obj;
            JSONArray jsonArray = (JSONArray) obj;

            Iterator<?> i = jsonArray.iterator();

            while (i.hasNext())
            {
                slide = (JSONObject) i.next();
                newsInfo = (String)slide.get(targetObject);   
                System.out.println(newsInfo);
                newsTitles.add(newsInfo);


            }
        } 
        catch (ParseException e) 
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

Upvotes: 0

Ash
Ash

Reputation: 101

By having a custom class and adding a type adapter u can manipulate the string (json.toString() returns with the '"' quotes, so you can see if its a string or not.

Output: (the classes seem correct)

class test.Main$StringPojo pojo{object=foo}

class test.Main$IntPojo pojo{object=1}

class test.Main$StringPojo pojo{object=bar}

class test.Main$StringPojo pojo{object=2}

class test.Main$IntPojo pojo{object=3}

public static void main(final String[] args){


    String str = "{\n" +
            "  \"text\": [\"foo\",1,\"bar\",\"2\",3],\n" +
            "  \"text1\": \"value1\" }";

    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(pojo.class, new JsonDeserializer<pojo>() {
        @Override
        public pojo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                return new IntPojo(Integer.parseInt(json.toString()));
            } catch (Exception e) {
                return new StringPojo(json.getAsString());
            }
        }
    });
    MyPojo myPojo = builder.create().fromJson(str, MyPojo.class);
    for (pojo pojo : myPojo.text) {
        System.out.println(pojo.getClass() + " " + pojo.object);
    }
}

public static abstract class  pojo{
    protected Object object;

    public pojo() {
    }

    @Override
    public String toString() {
        return "pojo{" +
                "object=" + object +
                '}';
    }
}

public static class StringPojo extends pojo{
    public StringPojo(String str) {
        object = str;
    }
}

public static class IntPojo extends pojo{

    public IntPojo(int intt) {
        this.object = intt;
    }
}
public static class MyPojo {
    List<pojo> text;
    String text1;
}

Upvotes: 1

Ashish Patil
Ashish Patil

Reputation: 4624

The above situation can be achived by using TypeAdapter of Gson API.

Please follow : https://sites.google.com/site/gson/gson-user-guide#TOC-Serializing-and-Deserializing-Collection-with-Objects-of-Arbitrary-Types

Upvotes: 0

Roberto Tellez Ibarra
Roberto Tellez Ibarra

Reputation: 2166

You can create an abstract class ItemType (for use as array item type) and inherits from it two wrapper classes: one for int type and another for string type.

abstract class ItemType {
    protected Object value;
}
class IntType extends ItemType {
    IntType(Integer value){
        this.value = value;
    }
}
class StringType extends ItemType {
    IntType(String value){
        this.value = value;
    }
}

Try this List<ItemType> text;

Upvotes: 0

user5117733
user5117733

Reputation:

As you wrote - you defined: List<String> text; but that list also contains integers.

Java is strongly typed, please consider to either declare the List as List<Object> (less preferable) or creating a JSON list that contains only a single type of variable (more preferable).

Upvotes: 0

Related Questions