0

Currently, I plan to convert the following Map<String, String> to List of POJO.

Map<String, String> m = new HashMap<>();
m.put("stock_price_alerts", "[{\"code\":\"KO\",\"rise_above\":7.0,\"size\":1000.89,\"price\":10,\"time\":1519625135173,\"fall_below\":null},{\"code\":\"BRK-B\",\"rise_above\":180,\"size\":100,\"price\":190,\"time\":1519160399911,\"fall_below\":null}]");
System.out.println(m);

When we print out the Map at console, it looks like

{stock_price_alerts=[{"code":"KO","rise_above":7.0,"size":1000.89,"price":10,"time":1519625135173,"fall_below":null},{"code":"BRK-B","rise_above":180,"size":100,"price":190,"time":1519160399911,"fall_below":null}]}

I prepare 2 POJO classes.

StockPriceAlert.java

package sandbox;

import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class StockPriceAlert {

    @SerializedName("code")
    @Expose
    public String code;
    @SerializedName("fall_below")
    @Expose
    public Object fallBelow;
    @SerializedName("rise_above")
    @Expose
    public long riseAbove;
    @SerializedName("price")
    @Expose
    public long price;
    @SerializedName("time")
    @Expose
    public long time;
    @SerializedName("size")
    @Expose
    public long size;

    /**
    * No args constructor for use in serialization
    * 
    */
    public StockPriceAlert() {
    }

    /**
    * 
    * @param fallBelow
    * @param time
    * @param price
    * @param riseAbove
    * @param code
    * @param size
    */
    public StockPriceAlert(String code, Object fallBelow, long riseAbove, long price, long time, long size) {
        super();
        this.code = code;
        this.fallBelow = fallBelow;
        this.riseAbove = riseAbove;
        this.price = price;
        this.time = time;
        this.size = size;
    }

}

StockPriceAlertResponse.java

package sandbox;

import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class StockPriceAlertResponse {

    @SerializedName("stock_price_alerts")
    @Expose
    private List<StockPriceAlert> stockPriceAlerts = null;

    /**
     * No args constructor for use in serialization
     *
     */
    public StockPriceAlertResponse() {
    }

    /**
     *
     * @param stockPriceAlerts
     */
    public StockPriceAlertResponse(List<StockPriceAlert> stockPriceAlerts) {
        super();
        this.stockPriceAlerts = stockPriceAlerts;
    }

    public List<StockPriceAlert> getStockPriceAlerts() {
        return stockPriceAlerts;
    }

    public void setStockPriceAlerts(List<StockPriceAlert> stockPriceAlerts) {
        this.stockPriceAlerts = stockPriceAlerts;
    }

}

I wrote the following code to perform conversion.

package sandbox;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author yccheok
 */
public class Main {  
    public static void main(String[] args) {
        Map<String, String> m = new HashMap<>();
        m.put("stock_price_alerts", "[{\"code\":\"KO\",\"rise_above\":7.0,\"size\":1000.89,\"price\":10,\"time\":1519625135173,\"fall_below\":null},{\"code\":\"BRK-B\",\"rise_above\":180,\"size\":100,\"price\":190,\"time\":1519160399911,\"fall_below\":null}]");

        System.out.println(m);

        final Gson gson = new GsonBuilder().create();

        JsonElement jsonElement = gson.toJsonTree(m);
        StockPriceAlertResponse stockPriceAlertResponse = gson.fromJson(jsonElement, StockPriceAlertResponse.class);
        List<StockPriceAlert> stockPriceAlerts = stockPriceAlertResponse.getStockPriceAlerts();
    }
}

However, I get the following Exception

Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING

Any idea how I can resolve this?

Note, Map<String, String> m is output from 3rd party library. So, that input is out of my control.

3
  • Every map value has to be converted separately with your approach. Commented Feb 26, 2018 at 10:48
  • @JoopEggen Sorry. I don't understand. Can you kindly explain more? Commented Feb 26, 2018 at 10:52
  • I have added an answer. Though @pirho also has a similar answer. Commented Feb 26, 2018 at 12:38

3 Answers 3

2

Do simply:

StockPriceAlertResponse res = gson.fromJson(""+m, StockPriceAlertResponse.class);

When m.toString() is called it generates something starting like:

{ stock_price_alerts= ...

but Gson seems to handle = even it should be :.

Note: you need to change

public long size;

to:

public float size;

because of values like:

"size": 1000.89
Sign up to request clarification or add additional context in comments.

Comments

1

The problem is that the original map's values will stay a String.

    String mJsonString = m.entrySet().stream()
            .map(e -> String.format("\"%s\":%s", e.getKey(), e.getValue()))
            .collect(Collectors.joining(",", "{", "}"));

    System.out.println(mJsonString);

    final Gson gson = new GsonBuilder().create();
    StockPriceAlertResponse stockPriceAlertResponse = gson.fromJson(mJsonString,
            StockPriceAlertResponse.class);
    List<StockPriceAlert> stockPriceAlerts = stockPriceAlertResponse.getStockPriceAlerts();

In the data is an error, for size: a floating point value that should have been integer.

Comments

1

Your problem is that you convert something that already is JSON into JSON again by calling toJsonTree. When you then call fromJson on the result it will convert it back to what you originally gave it: A Map<String, String>.

You have to call fromJson directly on the values in your map. Since the value you have is an array for whatever reason (enclosed by [ and ]), you have to first use fromJson with JsonArray.class, and then fromJson on the first element in the resulting array with your StockPriceAlert.class:

    for (String value : m.values())
    {
        StockPriceAlert stockPriceAlert = gson.fromJson(gson.fromJson(value, JsonArray.class).get(0), StockPriceAlert.class);
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.