Php Json关联数组到Java Map

时间:2012-09-11 19:07:56

标签: java php json gson

我的问题是,PHP根据它们是否连续编码来对数组进行不同的编码。从零索引开始,或不。例如:

$arr = array(array(12), array(13));
===> [[12], [13]]

$arr = array("0" => array(12), "1" => array(13));
===> [[12], [13]]

$arr = array("0" => array(12), "2" => array(13));
===> {"0": [12], "2": [13]}

为什么第三个如此根本不同?

第一个示例生成列表列表,第三个示例生成带列表的对象。我需要将所有这些转换为Java的Map<Integer, List<Double>>。这是我在Java中为这些PHP对象找到的最通用的数据类型。我正在使用谷歌的Gson。但是,由于这些示例会生成不同类型的对象,因此我无法将其读入地图。我必须首先检查它是否有索引,然后逐个添加到自定义地图。请查看“有必要采取更好的方式来完成这一部分”的界限。这是我的代码:

import java.lang.StringBuilder;
import com.google.gson.*;
import com.google.gson.reflect.*;
import java.util.Map;
import java.util.HashMap;
import java.util.List;

public class Saving {

    public static void main(String[] args) {

        String json = "[[12], [13]]";
        json = json.trim();
        Map<Integer, List<Double>> fuelSavings = null;

        // such a cluster****
        if(json.startsWith("[[")) { // THERE HAS TO BE A BETTER WAY TO DO THIS PART
        // ANY WAY I CAN AVOID THIS ENTIRE IF CONDITION

            //implicit keys
            fuelSavings = new HashMap<Integer, List<Double>>();
            List<List<Double>> temporaryList = new Gson().fromJson(json, new TypeToken<List<List<Double>>>(){}.getType());
            int index = 0;
            for(List<Double> temporaryListMember: temporaryList) {
                fuelSavings.put(index, temporaryListMember);
                index++;
            }

        } else {

            // explicit keys
            // THIS PART IS PERFECT
            fuelSavings = new Gson().fromJson(json, new TypeToken<Map<Integer, List<Double>>>(){}.getType());

        }

        System.out.println(fuelSavings);

    }

}

感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:0)

你在PHP中做的是两件不同的事情。 PHP中的数组用作数组,地图,列表。

即使在PHP中,

array(array(12), array(13));array("0" => array(12), "2" => array(13));也不一样。

使用Gson在Java中需要做的是将json解析为String并检查主对象是Map还是List然后建议。如果您已加载了List,那么您知道它是array(array(12), array(13));,否则它就是另一个。

你不能从PHP那里做一些事情来生成它总是一样的吗?

修改

如果您无法从PHP端执行任何操作,那么您的检查将与实例化JsonParser解析相同,然后检查JsonObject.isJsonArray()是否返回true,除非它最终会更快但您不会依靠gson库。

Map<Integer, List<Double>> fuelSavings = null;
JsonElement jElement = new JsonParser().parse("[[12], [13]]");
JsonObject jObject = jelement.getAsJsonObject();
if (jObject.isJsonArray()) {
    fuelSavings = new HashMap<Integer, List<Double>>();
    List<List<Double>> temporaryList = new Gson().fromJson(jElement, new TypeToken<List<List<Double>>>(){}.getType());
    int index = 0;
    for(List<Double> temporaryListMember: temporaryList) {
        fuelSavings.put(index++, temporaryListMember);
    }
} else /* this is a map */ {
    fuelSavings = new Gson().fromJson(jElement, new TypeToken<Map<Integer, List<Double>>>(){}.getType());
}

答案 1 :(得分:0)

非常有趣!

据我所知,PHP服务器将其数据作为编码为JSON的有序映射提供,但有时运气不好,其键是连续的整数,这使得json_encode()将其理解为一个简单的数组并使用不同的输出JSON的格式。

据我所知,所有PHP数组都是有序映射。但是当一个数组具有连续的整数键时,json_encode()生成一个没有键的数组,其中包含一个“JSON对象”(map)。这会破坏客户端的代码,而不是期望数组而不是“对象”。

令人难以置信的是,我发现没有现有的Java函数可以将JsonArray转换为JsonObject,如果我们尝试将数组作为对象,我们甚至可能会遇到一些异常!天哪,JsonArray只是带有隐式连续整数键的JsonObject,它应该自动生成! :P

我没试过,但也许JsonObject::entrySet()可以解决它。如果Integer自动解析String并且Set<Map.Entry<String,JsonElement>>可以使用正确的Map<Integer, AnyObject>进行转换,则返回JsonElement,可能会转换为TypeToken