How to maintain the order of a JSONObject

后端 未结 12 1607
栀梦
栀梦 2020-12-11 05:49

I am using a JSONObject in order to remove a certin attribute I don\'t need in a JSON String:

JSONObject jsonObject = new JSONObject(jsonString);
jsonObject.         


        
相关标签:
12条回答
  • I have faced the same problem recently and just transitioned all our tests (which expect JSON attributes to be in the same order) to another JSON library:

    <dependency>
        <groupId>org.codehaus.jettison</groupId>
        <artifactId>jettison</artifactId>
        <version>1.3.5</version>
    </dependency>
    

    Internally it uses a LinkedHashMap, which maintains the order of attributes. This library is functionally equivalent to the json.org library, so I don't see any reason why not use it instead, at least for tests.

    0 讨论(0)
  • 2020-12-11 06:17

    If you can edit the server repose then change it to array of JSON objects.

    JSON:

    [
    {PropertyName:"Date of Issue:",PropertyValue:"3/21/2011"},
    PropertyName:"Report No:",PropertyValue:"2131196186"},{PropertyName:"Weight:",PropertyValue:"1.00"},
    {PropertyName:"Report Type:",PropertyValue:"DG"}
    ]
    

    And I handled it with JSONArray in client side (Android):

    String tempresult="[{PropertyName:"Date of Issue:",PropertyValue:"3/21/2011"},PropertyName:"Report No:",PropertyValue:"2131196186"},PropertyName:"Weight:",PropertyValue:"1.00"},{PropertyName:"Report Type:",PropertyValue:"DG"}]"
    
    JSONArray array = new JSONArray(tempresult);
                 for (int i = 0; i < array.length(); i++) 
                 {
                     String key = array.getJSONObject(i).getString("PropertyName"); 
                     String value = array.getJSONObject(i).getString("PropertyValue");
                     rtnObject.put(key.trim(),value.trim()); //rtnObject is LinkedHashMap but can be any other object which can keep order.
    
    
             }
    
    0 讨论(0)
  • 2020-12-11 06:18

    You can use Jsckson library in case to maintain the order of Json keys. It internally uses LinkedHashMap ( ordered ).

    import com.fasterxml.jackson.core.JsonToken;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.node.ObjectNode;
    

    The code to remove a field, the removed JsonToken could itself be read if required.

      String jsonString = "{\"name\":\"abc\",\"address\":\"add\",\"data\":[\"some 1\",\"some 2\",\"some3 3\"],\"age\":12,\"position\":8810.21}";
      ObjectMapper mapper = new ObjectMapper();
      JsonNode node = mapper.readTree(jsonString);
      System.out.println("In original order:"+node.toString());
      JsonToken removedToken = ((ObjectNode) node).remove("address").asToken();
      System.out.println("Aft removal order:"+node.toString());
    

    ObjectNode implementation uses a LinkedHashMap, which maintains the insertion order:

     public ObjectNode(JsonNodeFactory nc) {
       super(nc);
       _children = new LinkedHashMap<String, JsonNode>();
     }
    
    0 讨论(0)
  • 2020-12-11 06:20

    This is not easy, the main idea is to use LinkedHashMap, either pass in to the constructor (JSONObject(Map map)), or modify bytecode to handle the String parameter (JSONObject(String source)), which is the main use case. I got a solution in oson:

        public static JSONObject getJSONObject(String source) {
        try {
            int lineNumberToReplace = 157;
    
            ClassPool classPool = ClassPool.getDefault();
            CtClass ctClass = classPool.get("org.json.JSONObject");
    
            if (ctClass.isFrozen() || ctClass.isModified()) {
                if (source == null) {
                    return new JSONObject();
                } else {
                    return new JSONObject(source);
                }
            }
    
            ctClass.stopPruning(true);
            CtConstructor declaredConstructor = ctClass.getDeclaredConstructor(new CtClass[] {}); 
    
            CodeAttribute codeAttribute = declaredConstructor.getMethodInfo().getCodeAttribute();
    
            LineNumberAttribute lineNumberAttribute = (LineNumberAttribute)codeAttribute.getAttribute(LineNumberAttribute.tag);
    
            // Index in bytecode array where the instruction starts
            int startPc = lineNumberAttribute.toStartPc(lineNumberToReplace);
    
            // Index in the bytecode array where the following instruction starts
            int endPc = lineNumberAttribute.toStartPc(lineNumberToReplace+1);
    
            // Let's now get the bytecode array
            byte[] code = codeAttribute.getCode();
            for (int i = startPc; i < endPc; i++) {
              // change byte to a no operation code
               code[i] = CodeAttribute.NOP;
            }
    
            declaredConstructor.insertAt(lineNumberToReplace, true, "$0.map = new java.util.LinkedHashMap();");
    
            ctClass.writeFile();
    
            if (source == null) {
                return (JSONObject) ctClass.toClass().getConstructor().newInstance();
            } else {
                return (JSONObject) ctClass.toClass().getConstructor(String.class).newInstance(source);
            }
    
        } catch (Exception e) {
            //e.printStackTrace();
        }
    
        if (source == null) {
            return new JSONObject();
        } else {
            return new JSONObject(source);
        }
    }
    

    need to include jar file from using mvn

    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>
    
    0 讨论(0)
  • 2020-12-11 06:24

    Go on JSONObject class Change from HashMap() to LinkedHashMap()

     /**
         * Construct an empty JSONObject.
         */
        public JSONObject() {
            this.map = new LinkedHashMap();
        }
    

    The LinkedHashMap class extends the Hashmap class. This class uses a doubly linked list containing all the entries of the hashed table, in the order in which the keys were inserted in the table: this allows the keys to be "ordered".

    0 讨论(0)
  • 2020-12-11 06:31

    I accomplished it by doing a:

    JSONObject(json).put(key, ObjectMapper().writeValueAsString(ObjectMapper().readValue(string, whatever::class)))

    So essentially I deserialize a string to an ordered class, then I serialize it again. But then I also had to format that string afterwards to remove escapes.

    .replace("\\\"", "\"").replace("\"{", "{").replace("}\"", "}")

    You may also have to replace null items as well if you don't want nulls.

    0 讨论(0)
提交回复
热议问题