转换地图<;字符串,字符串>;到POJO的列表-java.lang.IllegalStateException:应为BEGIN_数组,但为字符串

转换地图<;字符串,字符串>;到POJO的列表-java.lang.IllegalStateException:应为BEGIN_数组,但为字符串,java,gson,Java,Gson,目前,我计划将以下映射转换为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\":

目前,我计划将以下
映射
转换为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);
我准备了2节POJO课

StockPriceAlert.java StockPriceAlertResponse.java
包沙盒;
导入java.util.List;
导入com.google.gson.annotations.Expose;
导入com.google.gson.annotations.SerializedName;
公共类股票价格警报响应{
@SerializedName(“股票价格警报”)
@暴露
私有列表stockPriceAlerts=null;
/**
*没有用于序列化的args构造函数
*
*/
公共股票价格警报响应(){
}
/**
*
*@param-stockPriceAlerts
*/
public StockPriceAlertResponse(列出stockPriceAlerts){
超级();
this.stockPriceAlerts=stockPriceAlerts;
}
公共列表getStockPriceAlerts(){
返回股票价格警报;
}
公共无效设置股票价格警报(列出股票价格警报){
this.stockPriceAlerts=stockPriceAlerts;
}
}

我编写了以下代码来执行转换

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();
    }
}
包沙盒;
导入com.google.gson.gson;
导入com.google.gson.GsonBuilder;
导入com.google.gson.JsonElement;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
/**
*
*@作者yccheok
*/
公共类主{
公共静态void main(字符串[]args){
Map m=新的HashMap();
m、 看跌期权(“股票价格警报”)、“[{”代码\“:\”KO\”、\”上涨\“:7.0、\”大小\“:1000.89、\”价格\“:10、\”时间\“:1519625135173、\”下跌\“:空值\“:”BRK-B \“,”上涨\“:180、\”大小\“:100、\”价格\“:190、\”时间\“:1519160399911、\”下跌\“:空值\”);
系统输出打印项次(m);
final Gson Gson=new GsonBuilder().create();
JsonElement JsonElement=gson.toJsonTree(m);
StockPriceAlertResponse StockPriceAlertResponse=gson.fromJson(jsonElement,StockPriceAlertResponse.class);
List stockPriceAlerts=stockPriceAlertResponse.getStockPriceAlerts();
}
}
但是,我得到了以下异常

线程“main”com.google.gson.JsonSyntaxException中的异常: java.lang.IllegalStateException:应为BEGIN_数组,但为字符串

你知道我该怎么解决这个问题吗


注意,
Map m
是从第三方库输出的。所以,这个输入是我无法控制的。

您的问题是,通过调用
toJsonTree
再次将已经是
JSON
的内容转换为
JSON
。然后,当您对结果调用
fromJson
时,它会将结果转换回您最初给它的值:A
映射

您必须直接对地图中的值调用
fromJson
。由于您拥有的值是一个数组,无论出于何种原因(由
[
]
括起),您必须首先将
fromJson
JsonArray.class
一起使用,然后将
fromJson
StockPriceAlert.class一起使用在结果数组的第一个元素上:

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

您的问题是,通过调用
toJsonTree
,将已经是
JSON
的内容再次转换为
JSON
。然后,当您对结果调用
fromJson
时,它会将结果转换回您最初给它的值:A
映射

您必须直接对地图中的值调用
fromJson
。由于您拥有的值是一个数组,无论出于何种原因(由
[
]
括起),您必须首先将
fromJson
JsonArray.class
一起使用,然后将
fromJson
StockPriceAlert.class一起使用在结果数组的第一个元素上:

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

问题是原始贴图的值将保持为字符串

    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();
String mJsonString=m.entrySet().stream()
.map(e->String.format(“\%s\”:%s”,e.getKey(),e.getValue()))
.collect(collector.joining(“,”,“{,“}”);
System.out.println(mJsonString);
final Gson Gson=new GsonBuilder().create();
StockPriceAlertResponse StockPriceAlertResponse=gson.fromJson(mJsonString,
StockPriceAlertResponse.class);
List stockPriceAlerts=stockPriceAlertResponse.getStockPriceAlerts();

数据中有一个错误,例如大小:一个本应为整数的浮点值。

问题是原始映射的值将保留为字符串

    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();
String mJsonString=m.entrySet().stream()
.map(e->String.format(“\%s\”:%s”,e.getKey(),e.getValue()))
.collect(collector.joining(“,”,“{,“}”);
System.out.println(mJsonString);
final Gson Gson=new GsonBuilder().create();
StockPriceAlertResponse StockPriceAlertResponse=gson.fromJson(mJsonString,
StockPriceAlertResponse.class);
List stockPriceAlerts=stockPriceAlertResponse.getStockPriceAlerts();
数据中有一个错误,例如大小:一个本应为整数的浮点值。

只需执行以下操作:

StockPriceAlertResponse res = gson.fromJson(""+m, StockPriceAlertResponse.class);
当调用
m.toString()
时,它会生成类似以下内容的开头:

{ stock_price_alerts= ...
但是,Gson似乎能够处理
=
,即使它应该是

注意:您需要更改

public long size;
致:

因为有这样的价值观:

"size": 1000.89
简单地做:

StockPriceAlertResponse res = gson.fromJson(""+m, StockPriceAlertResponse.class);
当调用
m.toString()
时,它会生成类似以下内容的开头:

{ stock_price_alerts= ...
但是,Gson似乎能够处理
=
,即使它应该是

注意:您需要更改

public long size;
致:

因为有这样的价值观:

"size": 1000.89

每个地图值都必须用你的方法单独转换。@JoopEggen抱歉。我不明白。你能再解释一下吗?我补充了一个答案。尽管@pirho也有类似的答案。每个地图值都必须用你的方法单独转换。@JoopEggen抱歉。我不明白。你能再解释一下吗?我补充了一个答案。尽管@pirho a