Заказ JSON перепутал - PullRequest
       7

Заказ JSON перепутал

52 голосов
/ 16 октября 2010

У меня проблема при попытке заставить мою страницу печатать 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}

Мне нужно это в порядке идентификатора пользователя, суммы, затем успеха. Уже пробовал переупорядочивать в коде, но безрезультатно. Я также пытался .append .... нужна помощь здесь спасибо !!

Ответы [ 11 ]

94 голосов
/ 07 февраля 2011

Вы не можете и не должны полагаться на порядок элементов в объекте JSON.

Из спецификации JSON в http://www.json.org/

Объект представляет собой неупорядоченный набор имен/ значение пары

Как следствие, библиотеки JSON могут изменять порядок элементов по своему усмотрению.Это не ошибка.

12 голосов
/ 20 апреля 2011

Я согласен с другими ответами.Вы не можете полагаться на порядок элементов 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

5 голосов
/ 10 июля 2015

из примера 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 голосов
/ 21 июня 2018

Основное намерение здесь - отправить заказанный объект 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"}

3 голосов
/ 22 марта 2016

Реальный ответ можно найти в спецификации, 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;
    }
}
2 голосов
/ 15 сентября 2015

Загрузите "json simple 1.1 jar" из этой 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

2 голосов
/ 16 октября 2010

Объекты JavaScript и JSON не могут установить порядок для ключей.Вы могли бы сделать это правильно в Java (на самом деле я не знаю, как работают объекты Java), но если это происходит с веб-клиентом или другим потребителем JSON, нет никакой гарантии относительно порядка ключей.

1 голос
/ 03 октября 2016

вы можете сохранить порядок, если вы используете JsonObject, который принадлежит com.google.gson: D

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

Использование этого JsonObject даже не беспокоит использование Map <>

CHEERS !!!

0 голосов
/ 10 октября 2017

Для кода Java создайте класс POJO для вашего объекта вместо JSONObject. и используйте JSONEncapsulator для вашего класса POJO. таким образом, порядок элементов зависит от порядка установки геттеров в вашем классе POJO. например Класс 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: {// порядок атрибутов такой же, как порядок установки геттера.}}

0 голосов
/ 10 января 2017

Для тех, кто использует 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 , но переключите егореализация карты с LinkedHashMap , которую @lemiorhan отметил выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...