8

我们正在对一个非常不一致的 (Zurmo-)REST API 进行一些集成。API 仅接受 urlencoded 字符串作为其在 http 帖子中的有效负载,但它使用 JSON 进行回答。因此,由于文档对此非常不清楚,我们自然认为我们可以将 JSON 发布到其中,但事实并非如此。

因此,当我们需要将其作为 x-www-form-urlencoded 发送时,现在我们所有的代码都生成了 JSON,是否有任何java库可以将 JSON 转换为 urlencoded 字符串?

我们目前正在使用 org.json 库,但如果需要,我们可以更改它。

例子:

这个 JSON 字符串:

{"data":{"description":"test","occurredOnDateTime":"2013-10-24 01:44:50"}}

应该转换成这样:

data%5Bdescription%5D=test&data%5BoccurredOnDateTime%5D=2013-10-24+01%3A44%3A50

Java代码:

我们将 rasmushaglunds javascript 代码翻译成 java 并包装它,如果其他人偶然发现这个问题,这就是结果。

public static String jsonToURLEncoding(JSONObject json) {
    String output = "";
    String[] keys = JSONObject.getNames(json);
    for (String currKey : keys)
        output += jsonToURLEncodingAux(json.get(currKey), currKey);

    return output.substring(0, output.length()-1);
}

private static String jsonToURLEncodingAux(Object json, String prefix) {
    String output = "";
    if (json instanceof JSONObject) {
        JSONObject obj = (JSONObject)json;
        String[] keys = JSONObject.getNames(obj);
        for (String currKey : keys) {
            String subPrefix = prefix + "[" + currKey + "]";
            output += jsonToURLEncodingAux(obj.get(currKey), subPrefix);
        }
    } else if (json instanceof JSONArray) {
        JSONArray jsonArr = (JSONArray) json;
        int arrLen = jsonArr.length();

        for (int i = 0; i < arrLen; i++) {
            String subPrefix = prefix + "[" + i + "]";
            Object child = jsonArr.get(i);
            output += jsonToURLEncodingAux(child, subPrefix);
        }
    } else {
        output = prefix + "=" + json.toString() + "&";
    }

    return output;
}
4

3 回答 3

5
public static String objectToUrlEncodedString(Object object, Gson gson) {
    return jsonToUrlEncodedString((JsonObject) new JsonParser().parse(gson.toJson(object)));
}

private static String jsonToUrlEncodedString(JsonObject jsonObject) {
    return jsonToUrlEncodedString(jsonObject, "");
}

private static String jsonToUrlEncodedString(JsonObject jsonObject, String prefix) {
    String urlString = "";
    for (Map.Entry<String, JsonElement> item : jsonObject.entrySet()) {
        if (item.getValue() != null && item.getValue().isJsonObject()) {
            urlString += jsonToUrlEncodedString(
                    item.getValue().getAsJsonObject(),
                    prefix.isEmpty() ? item.getKey() : prefix + "[" + item.getKey() + "]"
            );
        } else {
            urlString += prefix.isEmpty() ?
                    item.getKey() + "=" + item.getValue().getAsString() + "&" :
                    prefix + "[" + item.getKey() + "]=" + item.getValue().getAsString() + "&";
        }
    }
    return urlString;
}
于 2016-05-16T16:39:42.940 回答
4

如下所述,它不是 Java 库,但您应该能够翻译它 :)

以下是您可以在 javascript 中执行此操作的方法:

var jsonArrayToUrl = function (obj, prefix) {
  var urlString = "";
  for (var key in obj) {
    if (obj[key] !== null && typeof obj[key] == "object") {
      prefix += "[" + key + "]";
      urlString += jsonArrayToUrl(obj[key], prefix);
    }else{
      urlString += prefix + "[" + key + "]=" + obj[key] + "&";
    }
  }
  return encodeURIComponent(urlString);
};

然后调用它

jsonArrayToUrl(test["data"], "data");

通过您在上面给出的示例字符串,它返回

"data%5Bdescription%5D%3Dtest%26data%5BoccurredOnDateTime%5D%3D2013-10-24%2001%3A44%3A50%26"

它应该在嵌套数组上递归工作。您也可以考虑为该函数编写一个包装器,以便您只需要一个参数。

于 2013-10-24T06:26:26.587 回答
3

现在有一个更简单的方法,那就是使用URLEncoder.encode方法。

导入URLEncoder包:

import java.net.URLEncoder; 

接着:

URLEncoder.encode(objectMapper.writeValueAsString(<yourClass>), StandardCharsets.UTF_8.toString());

你可以在这里测试你的结果:

https://onlinejsontools.com/url-decode-json

于 2021-08-09T13:24:04.217 回答