使用 Retrofit 解析动态密钥 Json 字符串

Posted

技术标签:

【中文标题】使用 Retrofit 解析动态密钥 Json 字符串【英文标题】:Parse Dynamic Key Json String using Retrofit 【发布时间】:2016-02-18 22:07:53 【问题描述】:

我正在尝试解析以下动态密钥 Json 字符串。

"report":
    "data":
        "results":
            "558952cca6d73d7d81c2eb9d":
                "Max":-1,
                "Min":-1,
                "Slope":-1,
            ,

            "558ce148a6d73d7d81c2fa8a":
                "Max":-2,
                "Min":-1,
                "Slope":-2,
            
        
    

以下我正在尝试获取数据,但在解析最后一个动态 json 字符串时出错。

 public class Report 
        @SerializedName("data")
        @Expose
        private Data data;

        public Data getData() 
            return data;
        

        public void setData(Data data) 
            this.data = data;
        

        @Override
        public String toString() 
            return "Report" +
                    "data=" + data +
                    '';
        
    

    public class Data 
        @SerializedName("results")
        @Expose
        private ResultInside result;

        public ResultInside getResult() 
            return result;
        

        public void setResult(ResultInside result) 
            this.result = result;
        
    

    public class ResultInside 
        /*@SerializedName("results")
        @Expose*/
        private Map<String, Vitals> elemDetails = new HashMap<>();

        public Map<String, Vitals> getElemDetails() 
            return elemDetails;
        

        public void setElemDetails(Map<String, Vitals> elemDetails) 
            this.elemDetails = elemDetails;
        
    

在这种情况下如何解析的任何建议!

【问题讨论】:

您好!你找到解决办法了吗?我遇到了同样的问题。 @GenkaKasyan 检查下面接受的答案。 @Shubh Hai,我也有同样的问题,我不知道如何为动态密钥添加 Pojo 类,你能告诉你在 Vitals 类中使用了什么吗? @MathaN 检查 json 字符串和受尊重的数据类。报告 -> 数据 -> 结果 -> 生命体征。如此重要的包含最大、最小、斜率作为变量。我确实错误地在 Result 中创建了另一个 ResulInside 类,它会将 runtime KeyVitals 类映射,但事实并非如此。检查下面接受的答案,而不是创建 ResultInsid 处理它 Result 类本身。 【参考方案1】:

您的 resultInside 类正在添加一个额外的对象层,该层在您的 JSON 中不存在。尝试将地图移动到您的 Dataresults 字段。

public class Data 
    @SerializedName("results")
    @Expose
    private Map<String, Vitals> result;

    //....

【讨论】:

在改造中,如果你想用动态键(动态名称)解析 JSON,你肯定需要使用 HashMap。所以这个答案是我正确的+1。只需确保将 HashMap 放在具有静态名称(不是动态名称)的对象级别 非常感谢。你节省了我的时间:) 如果每个动态键的孩子之一是JSONObjects的JSONArray,如何处理(接收数据)情况。谢谢 您能解释一下为什么会这样吗?看起来 GSON 正在跳过动态命名的密钥,但我不明白为什么。【参考方案2】:

更好的方法是:

----------------------

public class Report 
        @SerializedName("data")
        @Expose
        private Data data;

----------------------

public class Data 


    public HashMap<String, DataValues> dataValues;


    public Data() 
        this.dataVaues = new HashMap<>();
    


-----------------------------

然后,像这样创建一个 Parser 类:

public class DataParser implements JsonDeserializer<Data> 


    @Override
    public Data deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException 

        Data result = new Data();


        try 
            final HashMap<String, DataValues> map = readServiceUrlMap(json.getAsJsonObject());

            if(map != null) 
                result.dataValues = map;
            

        catch (JsonSyntaxException ex)
            return null;
        

        return result;
    


    private HashMap<String, DataValues> readServiceUrlMap(final JsonObject jsonObject) throws JsonSyntaxException 

        if(jsonObject == null) 
            return null;
        
        Gson gson = new Gson();

        HashMap<String, DataValues> products = new HashMap<>();

        for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) 

            String key = entry.getKey();
            DataValues value = gson.fromJson(entry.getValue(), DataValues.class);
            products.put(key, value);
        
        return products;
    


----------------------------------------------

之后,在你的 ApiClient 类中输入这个

public class ApiClient 


    private static Retrofit retrofit = null;

    public static Retrofit getClient(String baseUrl) 

        if(retrofit == null) 

            GsonBuilder gsonBuilder = new GsonBuilder();
            gsonBuilder.registerTypeAdapter(Data.class, new DataParser());

            retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create(gsonBuilder.create()))
                    .build();

我希望这会对某人有所帮助

【讨论】:

Ruben Caster,这里的 DataValues 类是什么? 您自己的带有用例信息的模型(DATA 中的类 -> public HashMap dataValues;

以上是关于使用 Retrofit 解析动态密钥 Json 字符串的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Retrofit 2和Gson来模拟JSON响应“密钥”频繁更改的数据

如何使用 Retrofit .... 解析嵌套的 json?

如何在Retrofit中同时解析多种数据格式

使用 Retrofit 解析本地 JSON 文件中的文本

使用 Retrofit 解析数组内的动态数组

如何使用 Retrofit 解析 json