按特定顺序打印jsonObject

时间:2017-06-18 20:11:15

标签: java json gson

是否可以按特定顺序打印jsonObject? 这就是我所拥有的

import NPC.NPCHandler;
import NPC.NPCDrops;
import com.google.gson.*;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import java.io.FileWriter;

/**
 * @author Ruud.
 */
public class Main {

    public static NPCDrops npcDrops = new NPCDrops();
    public static NPCHandler npcHandler = new NPCHandler();

    public static void main(String args[]) {
        /*for (int i = 1; i < npcs.length; i++)
            System.out.println(npcs[i].absX);*/
        JSONObject NPCDefinition = new JSONObject();
        NPCDefinition.put("New", "Tester");
        NPCDefinition.put("B", "Test");
        NPCDefinition.put("A", "Test");
        NPCDefinition.put("Test", "Tester");
        JSONArray NPCDefinitions = new JSONArray();
        NPCDefinitions.add(0, NPCDefinition);
        //NPCDefinitions.add(1, NPCDefinition);
        try (FileWriter file = new FileWriter("./Json/NPCDefinitions.json")) {
            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            JsonParser jp = new JsonParser();
            JsonElement je = jp.parse(NPCDefinitions.toJSONString());
            String prettyJsonString = gson.toJson(je);
            System.out.println(prettyJsonString);
            //file.write(prettyJsonString);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这是它返回的内容

[
  {
    "New": "Tester",
    "A": "Test",
    "B": "Test",
    "Test": "Tester"
  }
]

是否可以像放入物体一样返回它? 我想要这个,因为我正在使用JSON将游戏中的NPC系统转换为新的更好的系统,但我希望命令采用人类逻辑的方式,例如

[
  {
    "id": 0,
    "name": "Hans",
    "examine": "Servant of the Duke of Lumbridge.",
    "combat": 0,
    "size": 1
  },
  {
    "id": 1,
    "name": "Man",
    "examine": "One of many citizens.",
    "combat": 2,
    "drops": [
      {
        "id": 995,
        "amount": "1000",
        "chance": 0.50
      },
      {
        "id": 4151,
        "amount": "1",
        "chance": 1
      }
    ],
    "size": 1
  }
]

我还没有使用这些变量对它进行测试,但我确信它也会破坏订单,所以我想知道是否有办法保持这个顺序。我知道JSONObject不可能这样做,因为它是一个无序的列表或其他东西,但这不能以任何其他方式实现吗?

3 个答案:

答案 0 :(得分:1)

JSON-Objects并不关心其属性的顺序。

可能存在处理输入顺序的JSON库的实现。但是我不建议依赖任何JSON库处理的输入顺序作为JSON-Object,并且应该保持关联的断言(键值)并且键是无序的。

因此没有内在的可能性来保留输入顺序。唯一的方法是模拟它:您必须记住订单ID并编写您自己的输出器,在输出期间考虑订单ID。

答案 1 :(得分:1)

JSON对象是无序的K / V集,但并不意味着需要严格的顺序,因此它可以完全由实现驱动。

你在这里缺少的是混合两个不同的库:JSON Simple和Gson。我以前从未使用过JSON Simple,但即使快速查看该库也会发现它的org.json.simple.JSONObject扩展了原始HashMap,不同的JRE版本的顺序可能不同。与org.json.simple.JSONObject不同,Gson的原生com.google.gson.JsonObject会保留插入顺序(请参阅JsonObject implementation的更多信息 - 只是因为它以这种方式实现)。同样的混音故事发送到org.json.simple.JSONArraycom.google.gson.JsonArray。因此,最简单的解决方案就是摆脱JSON Simple,而不是混合两个不同的库,只使用Gson工具,如下所示:

private static final Gson gson = new GsonBuilder()
        .setPrettyPrinting()
        .create();

public static void main(final String... args) {
    final JsonObject npcDefinition = new JsonObject();
    npcDefinition.addProperty("New", "Tester");
    npcDefinition.addProperty("B", "Test");
    npcDefinition.addProperty("A", "Test");
    npcDefinition.addProperty("Test", "Tester");
    final JsonArray npcDefinitions = new JsonArray();
    npcDefinitions.add(npcDefinition);
    final String json = gson.toJson(npcDefinitions);
    System.out.println(json);
}

另请注意,此处不需要toString()调用(由于内存中的字符串分配,这可能非常昂贵),因为Gson使用其JsonElement子类非常完美。因此,保留了原始订单:

[
  {
    "New": "Tester",
    "B": "Test",
    "A": "Test",
    "Test": "Tester"
  }
]

由于对象是无序的,你甚至不应该依赖这个实现(我使用Gson 2.8.0) - 如果有一天新的Gson实现会破坏这个规则并打破倒退怎么办?无论出于何种原因,主要版本的兼容性(让我们说,假设的Gson 3)?这似乎与使用反射生成/使用JSON的序列化器/反序列化器相关(例如,ReflectiveTypeAdapterFactory)。为了保证顺序,我能想到的最强大的解决方案是直接写入输出流,比如说:

@SuppressWarnings("resource")
public static void main(final String... args)
        throws IOException {
    final JsonWriter jsonWriter = new JsonWriter(new OutputStreamWriter(System.out));
    jsonWriter.setIndent("  ");
    jsonWriter.beginArray();
    jsonWriter.beginObject();
    jsonWriter.name("New").value("Tester");
    jsonWriter.name("B").value("Tester");
    jsonWriter.name("A").value("Tester");
    jsonWriter.name("Test").value("Tester");
    jsonWriter.endObject();
    jsonWriter.endArray();
    jsonWriter.flush();
}
[
  {
    "New": "Tester",
    "B": "Tester",
    "A": "Tester",
    "Test": "Tester"
  }
]

答案 2 :(得分:0)

定义模型的方式将影响序列化到Json的顺序。这样的事情应该有效:

public class MyModel {
    public int id;
    public string name;
    public string examine;
    public int combat;
    public List<Drop> drops;
    public int size;
}