Jackson第四篇【Find方法寻值】

本文介绍如何使用Jackson库的find方法高效地从JSON字符串中提取特定字段的值,并提供了获取所有匹配值及首个匹配值的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第二章写了一种自己写的方法来查找json字符串中的值,其实jackson还提供一个find方法来查找json字符串中的值。今天我们一起来看看这个方法的使用……

按照惯例我先贴上代码

  1. / 
  2.   具体的类我就不贴出来浪费空间了 
  3.    
  4.   @param args 
  5.   @throws Exception 
  6.  */  
  7. public static void main(String[] args) throws Exception {  
  8.     // 准备数据  
  9.     List<Person> pers = new ArrayList<Person>();  
  10.     List<Person> childs = new ArrayList<Person>();  
  11.     Person p = new Person(“张三”46);  
  12.     childs.add(new Person(“小张三1”20));  
  13.     childs.add(new Person(“小张三2”17));  
  14.     p.setChilds(childs);  
  15.     pers.add(p);  
  16.     p = new Person(“李四”29);  
  17.     childs = new ArrayList<Person>();  
  18.     childs.add(new Person(“小李四1”20));  
  19.     p.setChilds(childs);  
  20.     pers.add(p);  
  21.     p = new Person(“王二麻子”23);  
  22.     pers.add(p);  
  23.     TestVo vo = new TestVo(null, pers);  
  24.     ObjectMapper mapper = JsonProcessUtil.getMapperInstance(false);  
  25.     String voJson = JsonProcessUtil.toJson(vo);  
  26.     JsonNode node = mapper.readTree(voJson);  
  27.     getValueByFind(node, ”age”);  
  28.     getFirstValueByFind(node, ”age”);  
  29.   
  30. }  
 / 
* 具体的类我就不贴出来浪费空间了
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 准备数据
List<Person> pers = new ArrayList<Person>();
List<Person> childs = new ArrayList<Person>();
Person p = new Person(“张三”, 46);
childs.add(new Person(“小张三1”, 20));
childs.add(new Person(“小张三2”, 17));
p.setChilds(childs);
pers.add(p);
p = new Person(“李四”, 29);
childs = new ArrayList<Person>();
childs.add(new Person(“小李四1”, 20));
p.setChilds(childs);
pers.add(p);
p = new Person(“王二麻子”, 23);
pers.add(p);
TestVo vo = new TestVo(null, pers);
ObjectMapper mapper = JsonProcessUtil.getMapperInstance(false);
String voJson = JsonProcessUtil.toJson(vo);
JsonNode node = mapper.readTree(voJson);
getValueByFind(node, “age”);
getFirstValueByFind(node, “age”);

}</pre>


 

哈哈,这样写是不是比第二篇里面的方便多了?但是有个缺点啊,不能指定路径。也就是说它会把当前json字符串中的所有匹配属性的值都取出来,如果你没有指定路径的要求 这种方法无疑很方便。

好了贴上两个方法的代码……

  1. / 
  2.   使用find的方法从实体中取出所有匹配的值 
  3.    
  4.   @param vo 
  5.   @param path 
  6.   @return 
  7.  /  
  8. public static List<String> getValueByFind(JsonNode node, String path) throws Exception {  
  9.     List<String> values = new ArrayList<String>();  
  10.     / 
  11.       values = node.findValuesAsText(path); 这里提供两种方法 一种是只填写path 
  12.       它会返回List<String>,另外一种就是下面用的 它会直接把找到的value填到你传入的集合中 
  13.      /  
  14.     node.findValuesAsText(path, values);  
  15.     System.out.println(Arrays.toString(values.toArray()));  
  16.     return values;  
  17. }  
   / 
* 使用find的方法从实体中取出所有匹配的值
*
* @param vo
* @param path
* @return
*/
public static List<String> getValueByFind(JsonNode node, String path) throws Exception {
List<String> values = new ArrayList<String>();
/*
* values = node.findValuesAsText(path); 这里提供两种方法 一种是只填写path
* 它会返回List<String>,另外一种就是下面用的 它会直接把找到的value填到你传入的集合中
*/
node.findValuesAsText(path, values);
System.out.println(Arrays.toString(values.toArray()));
return values;
}


 

  1. / 
  2.   查找当前Node中第一个匹配的值 
  3.    
  4.   @param node 
  5.   @param path 
  6.   @return 
  7.   @throws Exception 
  8.  /  
  9. public static int getFirstValueByFind(JsonNode node, String path) throws Exception {  
  10.     / 
  11.       注意这点不能使用getTextValue()方法,因为找到的值为Int类型的所以使用getTextValue是查不到值的。 
  12.       不过如果想返回String字符串可以使用asText()方法。这里使用asInt是为了看到其实JackSon是可以直接返回相应类型的值的。 
  13.      */  
  14.     int value = node.findValue(path).asInt();  
  15.     System.out.println(value);  
  16.     return value;  
  17. }  
 / 
* 查找当前Node中第一个匹配的值
*
* @param node
* @param path
* @return
* @throws Exception
*/
public static int getFirstValueByFind(JsonNode node, String path) throws Exception {
/*
* 注意这点不能使用getTextValue()方法,因为找到的值为Int类型的所以使用getTextValue是查不到值的。
* 不过如果想返回String字符串可以使用asText()方法。这里使用asInt是为了看到其实JackSon是可以直接返回相应类型的值的。
*/
int value = node.findValue(path).asInt();
System.out.println(value);
return value;
}


 

其实Jackson中的JsonNode还有许多其它方法,都可以根据名字来看出它的含义。可以尝试着进行学习……

<think>在Java中,枚举类(Enum)是一种特殊的类,它包含固定数量的常量。每个枚举常量都有一个默认的序数(ordinal),从0开始,也可以为枚举常量指定自定义的int。通常有两种方式获取枚举的int:1.使用枚举常量的`ordinal()`方法,它返回枚举常量在枚举声明中的位置,第一个常量的序数为0。2.自定义一个字段来存储int,并通过一个方法(如`getValue()`)来获取。下面分别给出示例:###方法1:使用`ordinal()`这种方法简单,但不够灵活,因为ordinal的取决于枚举常量的声明顺序。如果改变顺序或插入新的常量,ordinal会改变。```javapublicenumStatus{PENDING,//ordinal0ACTIVE,//ordinal1INACTIVE,//ordinal2DELETED//ordinal3}//获取ordinalintvalue=Status.ACTIVE.ordinal();//返回1```###方法2:自定义int更常见的做法是为每个枚举常量指定一个自定义的int,这样即使枚举常量的顺序改变,也不会变。```javapublicenumStatus{PENDING(10),ACTIVE(20),INACTIVE(30),DELETED(40);privatefinalintvalue;privateStatus(intvalue){this.value=value;}publicintgetValue(){returnvalue;}}//获取自定义intintvalue=Status.ACTIVE.getValue();//返回20```###完整示例代码下面是一个完整的示例,展示如何定义枚举并获取其int(自定义方式):```javapublicenumHttpStatus{//枚举常量,每个常量有一个对应的int(HTTP状态码)OK(200),CREATED(201),ACCEPTED(202),BAD_REQUEST(400),UNAUTHORIZED(401),FORBIDDEN(403),NOT_FOUND(404),INTERNAL_SERVER_ERROR(500);privatefinalintstatusCode;//枚举的构造方法必须是私有的privateHttpStatus(intstatusCode){this.statusCode=statusCode;}//提供方法获取intpublicintgetStatusCode(){returnstatusCode;}//可选:根据int获取枚举常量publicstaticHttpStatusfromStatusCode(intstatusCode){for(HttpStatusstatus:values()){if(status.statusCode==statusCode){returnstatus;}}thrownewIllegalArgumentException("Invalidstatuscode:"+statusCode);}}//使用示例publicclassMain{publicstaticvoidmain(String[]args){HttpStatusstatus=HttpStatus.OK;intcode=status.getStatusCode();//200System.out.println("HTTPStatusCode:"+code);//通过状态码获取枚举HttpStatusnotFound=HttpStatus.fromStatusCode(404);System.out.println(notFound);//输出NOT_FOUND}}```###解释1.**枚举定义**:枚举常量后面跟着括号和参数,这表示调用枚举的构造函数。2.**构造函数**:枚举的构造函数必须是私有的,因为枚举常量是在枚举内部定义的,外部不能创建枚举实例。3.**自定义字段**:每个枚举常量都有一个`statusCode`字段,通过构造方法初始化。4.**获取**:通过`getStatusCode()`方法获取自定义的int。5.**反向查找**:提供了`fromStatusCode`方法,通过int查找对应的枚举常量。###注意事项-使用`ordinal()`方法虽然简单,但是不推荐,因为它的依赖于枚举常量的声明顺序,容易在重构时出错。-自定义int方法更灵活,且可以赋予有意义的数。###在Kotlin中的实现如果你使用Kotlin,可以这样实现:```kotlinenumclassStatus(valvalue:Int){PENDING(10),ACTIVE(20),INACTIVE(30),DELETED(40)}//使用valvalue=Status.ACTIVE.value//20```同样,Kotlin也提供了`ordinal`属性,但同样不建议依赖它。§§相关问题§§:1.如何为枚举常量添加多个属性(例如,除了int外,再添加一个字符串描述)?2.在Java中,如何实现枚举常量的反向查找(通过int获取枚举常量)?如何提高反向查找的效率?3.枚举类在内存中是如何存储的?每个枚举常量会创建多少个实例?4.在序列化和反序列化过程中,如何正确地处理枚举的int(例如,使用Jackson库)?</think>### 枚举类获取其 int 详解 在 Java 中,枚举类获取 int 主要有两种方式:使用 `ordinal()` 方法和自定义字段。以下是详细说明和代码示例: #### 1. 使用 `ordinal()` 方法(内置方法) 每个枚举常量都有一个默认的 `ordinal()` 方法,返回其在枚举声明中的位置(从 0 开始)。 ```java public enum Status { PENDING, // ordinal = 0 APPROVED, // ordinal = 1 REJECTED, // ordinal = 2 CANCELLED // ordinal = 3 } public class Main { public static void main(String[] args) { // 获取枚举的 int int approvedValue = Status.APPROVED.ordinal(); System.out.println("APPROVED value: " + approvedValue); // 输出: 1 // 根据 int 获取枚举常量 Status status = Status.values()[2]; System.out.println("Status for 2: " + status); // 输出: REJECTED } } ``` **注意事项**: - 优点:简单易用,无需额外代码 - 缺点: - 完全依赖声明顺序 - 修改枚举顺序会改变所有 - 无法自定义特定 #### 2. 自定义字段(推荐方式) 通过构造函数为每个枚举常量指定自定义 int : ```java public enum HttpStatus { // 枚举常量与自定义 OK(200), CREATED(201), BAD_REQUEST(400), UNAUTHORIZED(401), FORBIDDEN(403), NOT_FOUND(404), INTERNAL_SERVER_ERROR(500); private final int code; // 自定义字段 // 枚举构造函数 HttpStatus(int code) { this.code = code; } // 获取自定义 int public int getCode() { return code; } // 根据 int 获取枚举常量 public static HttpStatus fromCode(int code) { for (HttpStatus status : values()) { if (status.code == code) { return status; } } throw new IllegalArgumentException("Invalid HTTP status code: " + code); } } public class Main { public static void main(String[] args) { // 获取自定义 int int notFoundCode = HttpStatus.NOT_FOUND.getCode(); System.out.println("NOT_FOUND code: " + notFoundCode); // 输出: 404 // 根据 int 获取枚举 HttpStatus status = HttpStatus.fromCode(500); System.out.println("Status for 500: " + status); // 输出: INTERNAL_SERVER_ERROR // 处理无效 try { HttpStatus invalid = HttpStatus.fromCode(999); } catch (IllegalArgumentException e) { System.out.println("Error: " + e.getMessage()); // 输出: Invalid HTTP status code: 999 } } } ``` #### 3. 高级优化:使用 Map 缓存 当枚举常量较多时,使用 Map 提高查找效率: ```java import java.util.HashMap; import java.util.Map; public enum ErrorCode { // 枚举常量 SUCCESS(0), INVALID_INPUT(1001), AUTH_FAILED(2001), DATABASE_ERROR(3001); private final int code; private static final Map<Integer, ErrorCode> CODE_MAP = new HashMap<>(); // 静态初始化填充 Map static { for (ErrorCode error : values()) { CODE_MAP.put(error.code, error); } } ErrorCode(int code) { this.code = code; } public int getCode() { return code; } public static ErrorCode fromCode(int code) { ErrorCode result = CODE_MAP.get(code); if (result == null) { throw new IllegalArgumentException("Invalid error code: " + code); } return result; } } ``` ### 关键区别对比 | 特性 | `ordinal()` 方法 | 自定义字段方法 | |--------------------------|-------------------------------|-----------------------------| | 来源 | 声明顺序 (0-based) | 自由指定 | | 修改安全性 | 低(改变顺序会破坏现有代码) | 高(固定不变) | | 可读性 | 差(数字无明确含义) | 好(有业务意义) | | 查找效率 | O(n)(需遍历) | O(1)(使用 Map 缓存) | | 适用场景 | 简单临时使用 | 生产环境推荐 | ### 最佳实践建议 1. **优先使用自定义字段** - 为枚举添加有业务意义的 int - 提供 `getCode()` 方法获取 - 实现 `fromCode()` 方法反向查找 2. **处理无效** - 在反向查找方法中抛出 `IllegalArgumentException` - 或返回 `Optional` 避免 NPE: ```java public static Optional<HttpStatus> fromCodeSafe(int code) { return Arrays.stream(values()) .filter(status -> status.code == code) .findFirst(); } ``` 3. **枚举序列化** - 在 JSON 序列化中(如 Jackson): ```java public class HttpStatusSerializer extends StdSerializer<HttpStatus> { public HttpStatusSerializer() { super(HttpStatus.class); } @Override public void serialize(HttpStatus value, JsonGenerator gen, SerializerProvider provider) { gen.writeNumber(value.getCode()); } } // 在枚举上使用注解 @JsonSerialize(using = HttpStatusSerializer.class) public enum HttpStatus { ... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值