简体   繁体   English

PHP Json关联数组到Java映射

[英]Php Json Associative Array To Java Map

My problem is, PHP encodes arrays differently, based on if they are consecutive & begin with a zero index, or not. 我的问题是,PHP根据数组是连续的还是以零索引开头的方式对数组进行不同的编码。 Example: 例:

$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]}

Why is the third one so radically different? 为什么第三个是如此不同?

The first example produces a list of lists, the third example produces an object with lists. 第一个示例产生一个列表列表,第三个示例产生一个带有列表的对象。 I need to convert all of these to Java 's Map<Integer, List<Double>> . 我需要将所有这些都转换为Java的Map<Integer, List<Double>> That is the most generic datatype I could find in Java for these PHP objects. 这是我可以在Java中为这些PHP对象找到的最通用的数据类型。 I am using Gson from Google. 我正在使用Google的Gson。 However, since the examples produces different types of objects, I cannot just read this into a map. 但是,由于这些示例生成了不同类型的对象,因此我不能仅将其读入地图。 I have to first check if it has indices and then adding one by one to a custom map. 我必须首先检查它是否具有索引,然后将其一个接一个地添加到自定义地图中。 Please look at the line that says "THERE HAS TO BE A BETTER WAY TO DO THIS PART". 请查看标有“做这部分的更好方法”的行。 This is my code: 这是我的代码:

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);

    }

}

Any help is appreciated, thanks! 任何帮助表示赞赏,谢谢!

What you do in PHP are two different things. 您在PHP中所做的是两件事。 Array in PHP serves as Arrays, Maps, Lists. PHP中的数组用作数组,地图,列表。

array(array(12), array(13)); and array("0" => array(12), "2" => array(13)); array("0" => array(12), "2" => array(13)); are not the same even in PHP. 即使在PHP中也不一样。

What you need to do in Java using Gson is to parse the json as String and check whether the main object is a Map or a List and then advise. 使用Gson在Java中需要做的是将json解析为String,并检查主要对象是Map还是List ,然后提出建议。 If you have loaded a List then you know it was a array(array(12), array(13)); 如果已加载列表,则知道它是一个array(array(12), array(13)); otherwise it was the other one. 否则就是另一个。

Can't you do something from the PHP side to generate it always the same? 您不能从PHP方面做一些事情来生成始终相同的东西吗?

Edit: 编辑:

If you cannot do anything from the PHP side then your check will be identical to instantiate a JsonParser parse then checking if JsonObject.isJsonArray() returns true, except that it will be eventually quicker but you won't rely on the gson library. 如果您不能从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());
}

Very interesting! 很有意思!

As I understood, PHP server serves its data as an ordered map encoded as JSON, but some times in a bad luck its keys are consecutive integers, which makes json_encode() understand it as a simple array and use a different format for the outputted JSON. 据我了解,PHP服务器将其数据作为编码为JSON的有序映射提供服务,但不幸的是,有时它的键是连续的整数,这使得json_encode()理解为简单数组,并为输出的JSON使用不同的格式。

As I understand, all PHP arrays are ordered maps. 据我了解,所有PHP数组都是有序映射。 But when one array has consecutive integer keys, json_encode() generates an array with no keys intead a "JSON Object" (map). 但是,当一个数组具有连续的整数键时, json_encode()在“ JSON Object”(映射)中插入一个没有键的数组。 And that breaks client's code that's not expecting an array instead of an "object". 这破坏了不希望使用数组而不是“对象”的客户代码。

Incredibly, I found no existing Java function to convert a JsonArray to a JsonObject , and we may even face some Exception sometimes if we try to get an array as an Object! 令人难以置信的是,我发现现有的Java函数都无法将JsonArray转换为JsonObject ,而且如果我们尝试将数组作为Object进行获取,有时甚至可能会遇到一些异常! Gosh, a JsonArray is just a JsonObject with implicit consecutive integer keys, it should be casted automatically!! 天哪,一个JsonArray只是一个具有隐式连续整数键的JsonObject ,应该自动JsonArray :p :p

I didn't try it, but maybe JsonObject::entrySet() can solve it. 我没有尝试过,但是也许JsonObject::entrySet()可以解决它。 It returns a Set<Map.Entry<String,JsonElement>> , which maybe may be converted to a Map<Integer, AnyObject> , if Integer parses String automatically and JsonElement can be converted with a proper TypeToken . 它返回一个Set<Map.Entry<String,JsonElement>> ,这也许可以被转换为一个Map<Integer, AnyObject>如果整数自动解析字符串和JsonElement可以用一个适当的转换TypeToken

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM