编写JSON字符串验证的更好方法

ax6ht2ek  于 2023-01-22  发布在  其他
关注(0)|答案(2)|浏览(144)
    • bounty将在6天后过期**。回答此问题可获得+50声望奖励。User27854希望引起更多人关注此问题。

我有一个JSON字符串:

{
  "productName": "Gold",
  "offerStartDate": "01152023",
  "offerEndDate": "01152024",
  "offerAttributes": [
    {
      "id": "TGH-DAD3KVF3",
      "storeid": "STG-67925",
      "availability": true
    }
  ],
  "offerSpecifications": {
    "price": 23.25
  }
}

相同的验证逻辑编写为

Map<String, Object> map = mapper.readValue(json, Map.class);
 
 String productNameValue = (String)map.get("productName");
 if(productNameValue ==null &&  productNameValue.isEmpty()) {
     throw new Exception();
 }
 
 String offerStartDateValue = (String)map.get("offerStartDate");
 if(offerStartDateValue ==null &&  offerStartDateValue.isEmpty()) {
     throw new Exception();
 }
 
 List<Object> offerAttributesValue = (List)map.get("offerAttributes");
 if(offerAttributesValue ==null &&  offerAttributesValue.isEmpty()) {
     throw new Exception();
 }
 
 Map<String, Object> offerSpecificationsValue = (Map)map.get("offerSpecifications");
 if(offerSpecificationsValue ==null &&  offerSpecificationsValue.isEmpty() &&  ((String)offerSpecificationsValue.get("price")).isEmpty()) {
     throw new Exception();
 }

这是JSON响应的一部分。实际的响应有超过48个字段。现有代码已经对所有48个字段进行了验证。注意,响应比这些复杂得多。
我觉得验证代码非常冗长,而且重复性很强。我该如何解决这个问题?我应该使用什么样的设计模式来编写验证逻辑。我看过构建器模式,但不确定如何将其用于此场景。

igsr9ssn

igsr9ssn1#

构建一个JSON模板用于比较。

ObjectMapper mapper = new ObjectMapper();
JsonNode template = mapper.readTree(
    "{" +
    "  \"productName\": \"\"," +
    "  \"offerStartDate\": \"\"," +
    "  \"offerEndDate\": \"\"," +
    "  \"offerAttributes\": []," +
    "  \"offerSpecifications\": {" +
    "    \"price\": 0" +
    "  }" +
    "}");
JsonNode data = mapper.readTree(
    "{" +
    "  \"productName\": \"Gold\"," +
    "  \"offerStartDate\": \"01152023\"," +
    "  \"offerEndDate\": \"01152024\"," +
    "  \"offerAttributes\": [" +
    "    {" +
    "      \"id\": \"TGH-DAD3KVF3\"," +
    "      \"storeid\": \"STG-67925\"," +
    "      \"availability\": true" +
    "    }" +
    "  ]," +
    "  \"offerSpecifications\": {" +
    "    \"price\": 23.25" +
    "  }" +
    "}");
validate(template, data);

下面是比较模板和数据的递归函数。

public void validate(JsonNode template, JsonNode data) throws Exception {
    final Iterator<Map.Entry<String, JsonNode>> iterator = template.fields();
    while (iterator.hasNext()) {
        final Map.Entry<String, JsonNode> entry = iterator.next();
        JsonNode dataValue = data.get(entry.getKey());
        if (dataValue == null || dataValue.isNull()) {
            throw new Exception("Missing " + entry.getKey());
        }
        if (entry.getValue().getNodeType() != dataValue.getNodeType()) {
            throw new Exception("Mismatch data type: " + entry.getKey());
        }
        switch (entry.getValue().getNodeType()) {
            case STRING:
                if (dataValue.asText().isEmpty()) {
                    throw new Exception("Missing " + entry.getKey());
                }
                break;
            case OBJECT:
                validate(entry.getValue(), dataValue);
                break;
            case ARRAY:
                if (dataValue.isEmpty()) {
                    throw new Exception("Array " + entry.getKey() + " must not be empty");
                }
                break;
        }
    }
}
tf7tbtn2

tf7tbtn22#

您好,您可以使用以下方法验证JSON:我创建了一个迷你的、按比例缩小的JSON版本,但它应该会为您指明正确的方向。
我使用了Jackson库,特别是我使用了对象Map器。下面是对象Map器的一些文档-https://www.baeldung.com/jackson-object-mapper-tutorial
所以我创建了一个简单的Product类。Product类由以下内容组成:
1.空构造函数
1.所有参数构造函数
1.三个私人属性,名称,价格,库存
1.吸气器和设置器
下面是我的Main.java代码。

import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        // Mock JSON
        String json = """
                {
                  "name" : "",
                  "price" : 5.99,
                  "inStock": true
                }""";

        // Declare & Initialise a new object mapper
        ObjectMapper mapper = new ObjectMapper();

        // Declare & Initialise a new product object
        Product product = null;
        try {
            // Try reading the values from the json into product object
            product = mapper.readValue(json, Product.class);
        }
        catch (Exception exception) {
            System.out.println("Exception");
            System.out.println(exception.getMessage());
            return;
        }

        // Map out the object's field names to the field values
        Map<String, Object> propertiesOfProductObject = mapper.convertValue(product, Map.class);

        // Loop through all the entries in the map. i.e. the fields and their values
        for(Map.Entry<String, Object> entry : propertiesOfProductObject.entrySet()){
            // If a value is empty throw an exception
            // Else print it to the console
            if (entry.getValue().toString().isEmpty()) {
                throw new Exception("Missing Attribute : " + entry.getKey());
            } else {
                System.out.println(entry.getKey() + "-->" + entry.getValue());
            }
        }
    }
}

它抛出一个错误,因为名称字段为空。

相关问题