JSON命令混淆了

时间:2010-10-16 08:51:36

标签: java json

我尝试按照我想要的顺序打印JSONObject页面时遇到问题。在我的代码中,我输入了这个:

JSONObject myObject = new JSONObject();
myObject.put("userid", "User 1");
myObject.put("amount", "24.23");
myObject.put("success", "NO");

但是,当我在页面上看到显示时,它会显示:

JSON格式化字符串:[{"success":"NO","userid":"User 1","bid":24.23}

我需要按用户ID,数量,然后成功的顺序。已经尝试在代码中重新排序,但无济于事。我也试过.append ....需要一些帮助,谢谢!!

17 个答案:

答案 0 :(得分:92)

您不能也不应该依赖JSON对象中元素的排序。

来自http://www.json.org/

的JSON规范
  

对象是一组无序的   名称/值对

因此, JSON库可以根据需要重新排列元素的顺序。 这不是一个错误。

答案 1 :(得分:11)

我同意其他答案。您不能依赖JSON元素的排序。

但是,如果我们需要一个有序的JSON,一个解决方案可能是使用元素准备 LinkedHashMap 对象并将其转换为JSONObject。

@Test
def void testOrdered() {
    Map obj = new LinkedHashMap()
    obj.put("a", "foo1")
    obj.put("b", new Integer(100))
    obj.put("c", new Double(1000.21))
    obj.put("d", new Boolean(true))
    obj.put("e", "foo2")
    obj.put("f", "foo3")
    obj.put("g", "foo4")
    obj.put("h", "foo5")
    obj.put("x", null)

    JSONObject json = (JSONObject) obj
    logger.info("Ordered Json : %s", json.toString())

    String expectedJsonString = """{"a":"foo1","b":100,"c":1000.21,"d":true,"e":"foo2","f":"foo3","g":"foo4","h":"foo5"}"""
    assertEquals(expectedJsonString, json.toString())
    JSONAssert.assertEquals(JSONSerializer.toJSON(expectedJsonString), json)
}

通常订单不会保留如下。

@Test
def void testUnordered() {
    Map obj = new HashMap()
    obj.put("a", "foo1")
    obj.put("b", new Integer(100))
    obj.put("c", new Double(1000.21))
    obj.put("d", new Boolean(true))
    obj.put("e", "foo2")
    obj.put("f", "foo3")
    obj.put("g", "foo4")
    obj.put("h", "foo5")
    obj.put("x", null)

    JSONObject json = (JSONObject) obj
    logger.info("Unordered Json : %s", json.toString(3, 3))

    String unexpectedJsonString = """{"a":"foo1","b":100,"c":1000.21,"d":true,"e":"foo2","f":"foo3","g":"foo4","h":"foo5"}"""

    // string representation of json objects are different
    assertFalse(unexpectedJsonString.equals(json.toString()))
    // json objects are equal
    JSONAssert.assertEquals(JSONSerializer.toJSON(unexpectedJsonString), json)
}

您也可以查看我的帖子:http://www.flyingtomoon.com/2011/04/preserving-order-in-json.html

答案 2 :(得分:5)

来自lemiorhan的例子 我可以通过改变一些lemiorhan的代码来解决 使用方法:

JSONObject json = new JSONObject(obj);

而不是:

JSONObject json = (JSONObject) obj

所以在我的测试代码中是:

Map item_sub2 = new LinkedHashMap();
item_sub2.put("name", "flare");
item_sub2.put("val1", "val1");
item_sub2.put("val2", "val2");
item_sub2.put("size",102);

JSONArray itemarray2 = new JSONArray();
itemarray2.add(item_sub2);
itemarray2.add(item_sub2);//just for test
itemarray2.add(item_sub2);//just for test


Map item_sub1 = new LinkedHashMap();
item_sub1.put("name", "flare");
item_sub1.put("val1", "val1");
item_sub1.put("val2", "val2");
item_sub1.put("children",itemarray2);

JSONArray itemarray = new JSONArray();
itemarray.add(item_sub1);
itemarray.add(item_sub1);//just for test
itemarray.add(item_sub1);//just for test

Map item_root = new LinkedHashMap();
item_root.put("name", "flare");
item_root.put("children",itemarray);

JSONObject json = new JSONObject(item_root);

System.out.println(json.toJSONString());

答案 3 :(得分:3)

真正的答案可以在规范中找到,json是无序的。 然而,作为一个人类读者,我按重要性排序了我的元素。它不仅是一种更逻辑的方式,而且更容易阅读。也许规范的作者从来不必阅读JSON,我这样做。所以,这里有一个修复:

/**
 * I got really tired of JSON rearranging added properties.
 * Specification states:
 * "An object is an unordered set of name/value pairs"
 * StackOverflow states:
 * As a consequence, JSON libraries are free to rearrange the order of the elements as they see fit.
 * I state:
 * My implementation will freely arrange added properties, IN SEQUENCE ORDER!
 * Why did I do it? Cause of readability of created JSON document!
 */
private static class OrderedJSONObjectFactory {
    private static Logger log = Logger.getLogger(OrderedJSONObjectFactory.class.getName());
    private static boolean setupDone = false;
    private static Field JSONObjectMapField = null;

    private static void setupFieldAccessor() {
        if( !setupDone ) {
            setupDone = true;
            try {
                JSONObjectMapField = JSONObject.class.getDeclaredField("map");
                JSONObjectMapField.setAccessible(true);
            } catch (NoSuchFieldException ignored) {
                log.warning("JSONObject implementation has changed, returning unmodified instance");
            }
        }
    }

    private static JSONObject create() {
        setupFieldAccessor();
        JSONObject result = new JSONObject();
        try {
            if (JSONObjectMapField != null) {
                JSONObjectMapField.set(result, new LinkedHashMap<>());
            }
        }catch (IllegalAccessException ignored) {}
        return result;
    }
}

答案 4 :(得分:3)

这里的主要目的是发送一个有序的JSON对象作为响应。我们不需要javax.json.JsonObject来实现。我们可以将有序的json创建为字符串。 首先以所需顺序创建一个具有所有键值对的LinkedHashMap。然后生成字符串形式的json,如下所示。 使用Java 8更加容易。

public Response getJSONResponse() {
    Map<String, String> linkedHashMap = new LinkedHashMap<>();
    linkedHashMap.put("A", "1");
    linkedHashMap.put("B", "2");
    linkedHashMap.put("C", "3");

    String jsonStr = linkedHashMap.entrySet().stream()
            .map(x -> "\"" + x.getKey() + "\":\"" + x.getValue() + "\"")
            .collect(Collectors.joining(",", "{", "}"));
    return Response.ok(jsonStr).build();
}

此函数返回的响应如下: {"A":"1","B":"2","C":"3"}

答案 5 :(得分:2)

JavaScript对象和JSON无法设置密钥的顺序。您可能在Java中正确使用它(我不知道Java对象是如何工作的),但如果它是用于Web客户端或JSON的另一个使用者,则无法保证密钥的顺序。

答案 6 :(得分:2)

下载&#34; json simple 1.1 jar&#34;来自https://code.google.com/p/json-simple/downloads/detail?name=json_simple-1.1.jar&can=2&q=

将jar文件添加到lib文件夹

使用JSONValue可以将LinkedHashMap转换为json字符串

如需更多参考,请点击此处http://androiddhina.blogspot.in/2015/09/ordered-json-string-in-android.html

答案 7 :(得分:1)

如果您使用属于com.google.gson的JsonObject,则可以保留订单:D

JsonObject responseObj = new JsonObject();
responseObj.addProperty("userid", "User 1");
responseObj.addProperty("amount", "24.23");
responseObj.addProperty("success", "NO");

使用这个JsonObject甚至不需要使用Map&lt;&gt;

CHEERS !!!

答案 8 :(得分:0)

只需使用 LinkedHashMap 保持顺序并使用 jackson 将其转换为 json

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.LinkedHashMap;

LinkedHashMap<String, Object> obj = new LinkedHashMap<String, Object>();
stats.put("aaa", "aaa");
stats.put("bbb", "bbb");
stats.put("ccc", "ccc");

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
System.out.println(json);

maven 依赖

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.9.10.7</version>
</dependency>

答案 9 :(得分:0)

ES6 你可以这样操作。订单将保持不变

 var Sorted=[];
 Sorted.push({test1:check1})
 Sorted.push({test2:check2})
 Sorted.push({test3:check3})

之所以有效,是因为我们正在一个接一个地推送键值对。通过这种方式,我们可以可靠地实现订购目标。

答案 10 :(得分:0)

不确定我是否迟到了,但我发现了这个很好的例子,它覆盖了 JSONObject 构造函数,并确保 JSON 数据以与添加相同的方式输出。在幕后 JSONObject 使用 MAP,而 MAP 不保证顺序,因此我们需要覆盖它以确保我们按照订单接收 JSON。

如果您将此添加到您的 JSONObject 中,那么生成的 JSON 将与您创建它的顺序相同。

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import org.json.JSONObject;
import lombok.extern.java.Log;

@Log
public class JSONOrder {

    public static void main(String[] args) throws IOException {

        JSONObject jsontest = new JSONObject();
        try {
            Field changeMap = jsonEvent.getClass().getDeclaredField("map");
            changeMap.setAccessible(true);
            changeMap.set(jsonEvent, new LinkedHashMap<>());
            changeMap.setAccessible(false);
        } catch (IllegalAccessException | NoSuchFieldException e) {
            log.info(e.getMessage());
        }
        jsontest.put("one", "I should be first");
        jsonEvent.put("two", "I should be second");
        jsonEvent.put("third", "I should be third");
        System.out.println(jsonEvent);
    }
}

答案 11 :(得分:0)

只需添加带有此标签的订单

@JsonPropertyOrder({ "property1", "property2"})

答案 12 :(得分:0)

我在我喜欢分享的“ interweb”上发现了一个“整洁”的反射调整。 (来源:https://towardsdatascience.com/create-an-ordered-jsonobject-in-java-fb9629247d76

这将通过反射API将org.json.JSONObject中的基础集合更改为无序集合(LinkedHashMap)。

我测试成功:

import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import org.json.JSONObject;

private static void makeJSONObjLinear(JSONObject jsonObject) {
    try {
            Field changeMap = jsonObject.getClass().getDeclaredField("map");
            changeMap.setAccessible(true);
            changeMap.set(jsonObject, new LinkedHashMap<>());
            changeMap.setAccessible(false);
        } catch (IllegalAccessException | NoSuchFieldException e) {
            e.printStackTrace();
        }
}

[...]
JSONObject requestBody = new JSONObject();
makeJSONObjLinear(requestBody);

requestBody.put("username", login);
requestBody.put("password", password);
[...]
// returned   '{"username": "billy_778", "password": "********"}' == unordered
// instead of '{"password": "********", "username": "billy_778"}' == ordered (by key)

答案 13 :(得分:0)

Underscore-java使用linkedhashmap存储JSON的键/值。我是该项目的维护者。

Map<String, Object> myObject = new LinkedHashMap<>();
myObject.put("userid", "User 1");
myObject.put("amount", "24.23");
myObject.put("success", "NO");

System.out.println(U.toJson(myObject));

答案 14 :(得分:0)

对于Java代码,为对象而不是JSONObject创建POJO类。 并为您的POJO类使用JSONEncapsulator。 这种方式的元素顺序取决于POJO类中getter setter的顺序。 例如。 POJO类就像

Class myObj{
String userID;
String amount;
String success;
// getter setters in any order that you want

以及您需要在响应中发送json对象的位置

JSONContentEncapsulator<myObj> JSONObject = new JSONEncapsulator<myObj>("myObject");
JSONObject.setObject(myObj);
return Response.status(Status.OK).entity(JSONObject).build();

此行的响应将是

{myObject:{//属性顺序与getter setter order。}}

答案 15 :(得分:0)

对于那些使用maven的人,请尝试com.github.tsohr/json

<!-- https://mvnrepository.com/artifact/com.github.tsohr/json -->
<dependency>
    <groupId>com.github.tsohr</groupId>
    <artifactId>json</artifactId>
    <version>0.0.1</version>
</dependency>

它从JSON-java分叉,但切换了@lemiorhan上面提到的地图实现with LinkedHashMap

答案 16 :(得分:0)

正如所有人都告诉你的那样,JSON没有维护“序列”但是阵列没有,也许这可以说服你: Ordered JSONObject