【问题标题】:How to Sort JsonNode by an object value in java如何在java中按对象值对JsonNode进行排序
【发布时间】:2021-02-11 23:53:01
【问题描述】:

如何根据产品节点的成本变量按升序或降序获得排序值?或者如何通过在下面的 JsonNode 响应中排序来修改产品节点的值?

JsonNode 响应:

{
    "products": [
        {
            "Name": "Marble",
            "cost": 47.49
        },
        {
            "Name": "Mixer",
            "cost": 59.99
        },
        {
            "Name": "Soap",
            "cost": 3.99
        }
    ],
    "details": [
        {
            "area": 1090.098
        }
    ]
}

降序的异常响应:

{
    "products": [
        {
            "Name": "Mixer",
            "cost": 59.99
        },
        {
            "Name": "Marble",
            "cost": 47.49
        },
        {
            "Name": "Soap",
            "cost": 3.99
        }
    ],
    "details": [
        {
            "area": 1090.098
        }
    ]
}

请用正确的解决方案指导我,我厌倦了使用比较器但是JsonNode响应中的这个产品节点没有任何POJO类,所以我不能使用obj.StringName进行比较。

【问题讨论】:

    标签: java arrays json sorting arraylist


    【解决方案1】:

    以下解决方案使用包javax.json.* 来解析和生成JSON

    import java.util.*;
    import java.io.*;
    import javax.json.*;
    
    public class Products
    {
        // This is an "internal" method that loads the JSON to a String
        static final String json = LFEC.loadFile("products.json");
        
        public static void main(String[] argv) throws IOException
        {
            // *********** Parse Input Json *****************
            // Save the products in a sorted TreeMap...
            // NOTE: We will have to "resort it" afterwards..
            // **********************************************
            TreeMap<String, Double> productsSortedByName = new TreeMap<>();
    
            // Retrieve the JsonObject's
            JsonObject   obj         = Json.createReader(new StringReader(json)).readObject();
            JsonArray    products    = obj.getJsonArray("products");
            
            for (JsonObject product : products.getValuesAs(JsonObject.class))
            {
                // Retreives the product name and price for each product
                String name = product.getString("Name");
                double cost = product.getJsonNumber("cost").doubleValue();
    
                // Save in a Java TreeMap<String, Double> 
                // NOTE:  TreeMap sorts by the "Key" (not the value)
    
                productsSortedByName.put(name, Double.valueOf(cost));
            }
            
            // ******** Sort Products by Price **************
            // Since the question requires that the TreeMap sort by price, not product name...
            // This shall build a new TreeMap that is sorted by the Price
            // This is tricky, because it requires having **TWO** TreeMap's
            // **********************************************
    
            Comparator<String> comp = (String key1, String key2) -> 
                productsSortedByName.get(key1).compareTo(productsSortedByName.get(key2));
    
            // Build the TreeMap, and put the contents of the original TreeMap into the new one
            TreeMap<String, Double> productsSortedByPrice = new TreeMap<>(comp);
            productsSortedByPrice.putAll(productsSortedByName);
            
            // ********* Products are Sorted ****************
            // Now build the sorted JSON - this part is "self-explanatory."
            // AGAIN, this is how the JDK package "javax.json.*" can be used to create JSON
            // ********* Build Output Json ******************
    
            JsonArrayBuilder arrBuilder = Json.createArrayBuilder();
            
            for (String product : productsSortedByPrice.keySet())
                arrBuilder.add(Json.createObjectBuilder()
                    .add("name", product)
                    .add("cost", productsSortedByPrice.get(product).doubleValue()));
            
            String sortedJson = Json
                .createObjectBuilder()
                .add("products", arrBuilder)
                .add("details", obj.getJsonArray("details"))
                .build()
                .toString();
            
            // Print out the sorted JSON to terminal...
            System.out.println(sortedJson);
        }
    }
    

    以上代码将在终端输出以下内容:

    {"products":[{"name":"Soap","cost":3.99},{"name":"Marble","cost":47.49},{"name":"Mixer","cost":59.99}],"details":[{"area":1090.098}]}
    

    【讨论】:

      【解决方案2】:

      如果您不想为数据模型创建 POJO,可以使用 javax.json.json-api 库直接使用 JSON。

      查看我的 maven 文件(在代码示例之后),了解我添加到项目中的依赖项列表。

      package so;
      import java.io.StringReader;
      import java.io.StringWriter;
      
      import javax.json.*;
      
      
      public class SortExample {
          
          public JsonObject sortProductsByPrice(JsonObject order) {
              
              JsonArray products = order.getJsonArray("products");
              JsonArray details = order.getJsonArray("details");
              
              JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
      
              
              products.stream().sorted((product1, product2) -> {
                  JsonNumber cost1 = product1.asJsonObject().getJsonNumber("cost");
                  JsonNumber cost2 = product2.asJsonObject().getJsonNumber("cost");
                  return Double.compare(cost1.doubleValue(), cost2.doubleValue());
              }).forEach((value) -> arrayBuilder.add(value));
              
              
              JsonObjectBuilder objectBuilder = Json.createObjectBuilder();
              
              objectBuilder.add("products", arrayBuilder.build());
              objectBuilder.add("details", details);
              
              return objectBuilder.build();
              
          }
      
          public static void main(String[] args) {
              
              String orderString = 
                      "{\"products\": [ {\"Name\": \"Marble\",\"cost\": 47.49 }, { \"Name\": \"Mixer\",  \"cost\": 59.99  },  { \"Name\": \"Soap\", \"cost\": 3.99  } ], \"details\" : [ { \"area\" : 1090.098  } ] }";
              
                      
              JsonObject order = Json.createReader(new StringReader(orderString)).readObject();
              
              JsonObject sortedOrder = new SortExample().sortProductsByPrice(order);
              
              StringWriter writer = new StringWriter();
              Json.createWriter(writer).writeObject(sortedOrder);
              
              System.out.println(writer.toString());
          }
      
      }
      

      打印:

      {"products":[{"Name":"Soap","cost":3.99},{"Name":"Marble","cost":47.49},{"Name":"Mixer","cost":59.99}],"details":[{"area":1090.098}]}
      

      我的示例中的main 方法只是从您的示例中构造有效负载。工作在sortProductsByPrice完成。

      它只是将产品保留在其JsonValue 表示中,并使用流式 API 对其进行排序,然后将它们放回新的JsonArray,最后使用原始details 和排序的产品构建一个新的JsonObject .

      我不熟悉 javax.json 并且找不到漂亮的打印选项。也许有更好的库可用。但这为您提供了您想要做什么的要点。

      依赖关系:

              <dependency>
                  <groupId>javax.json</groupId>
                  <artifactId>javax.json-api</artifactId>
                  <version>1.1.4</version>
              </dependency>
              <dependency>
                  <groupId>org.glassfish</groupId>
                  <artifactId>javax.json</artifactId>
                  <version>1.1.4</version>
              </dependency>
      

      【讨论】:

        猜你喜欢
        • 2013-05-21
        • 2023-02-03
        • 1970-01-01
        • 2012-12-24
        • 2011-11-16
        • 2015-07-03
        • 2014-04-03
        • 2010-10-29
        相关资源
        最近更新 更多