前端做商城网站需要多久,抖音代运营是什么意思,武昌做网站公司推荐,17网站一起做网店如何下单现在#xff0c;假设有一个与Car对象相对应的JSON字符串#xff0c;如下所示#xff1a;
{ “brand”:“Toyota”, “doors”:null }
请注意#xff0c;doors字段值为null。 Java中的基本数据类型不能为null值。 默认情况下#xff0c;Jackson ObjectMapper会忽略原始字…现在假设有一个与Car对象相对应的JSON字符串如下所示
{ “brand”:“Toyota”, “doors”:null }
请注意doors字段值为null。 Java中的基本数据类型不能为null值。 默认情况下Jackson ObjectMapper会忽略原始字段的空值。 但是可以将Jackson ObjectMapper配置设置为失败。
ObjectMapper objectMapper new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
在FAIL_ON_NULL_FOR_PRIMITIVES配置值设置为true的情况下尝试将空JSON字段解析为基本类型Java字段时会遇到异常。 这是一个Java Jackson ObjectMapper示例该示例将失败因为JSON字段包含原始Java字段的空值
ObjectMapper objectMapper new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, true);
String carJson “{ “brand”:“Toyota”, “doors”:null }”;
Car car objectMapper.readValue(carJson, Car.class);
结果 13、自定义反序列化
有时可能希望以不同于Jackson ObjectMapper缺省方式的方式将JSON字符串读入Java对象。 可以将自定义反序列化器添加到ObjectMapper可以按需要执行反序列化。
这是在Jackson的ObjectMapper中注册和使用自定义反序列化器的方式
String json “{ “brand” : “Ford”, “doors” : 6 }”;
SimpleModule module
new SimpleModule(“CarDeserializer”, new Version(3, 1, 8, null, null, null));
module.addDeserializer(Car.class, new CarDeserializer(Car.class));
ObjectMapper mapper new ObjectMapper();
mapper.registerModule(module);
Car car mapper.readValue(json, Car.class);
自定义反序列化器CarDeserializer类
public class CarDeserializer extends StdDeserializer {
public CarDeserializer(Class? vc) {
super(vc);
}
Override
public Car deserialize(JsonParser parser, DeserializationContext deserializer) throws IOException {
Car car new Car();
while(!parser.isClosed()){
JsonToken jsonToken parser.nextToken();
if(JsonToken.FIELD_NAME.equals(jsonToken)){
String fieldName parser.getCurrentName();
System.out.println(fieldName);
jsonToken parser.nextToken();
if(“brand”.equals(fieldName)){
car.setBrand(parser.getValueAsString());
} else if (“doors”.equals(fieldName)){
car.setDoors(parser.getValueAsInt());
}
}
}
return car;
}
}
二、将对象写入JSON 1、Java对象–JSON
Jackson ObjectMapper也可以用于从对象生成JSON。 可以使用以下方法之一进行操作 writeValue() writeValueAsString() writeValueAsBytes()
这是一个从Car对象生成JSON的示例和上面的实例相反
ObjectMapper objectMapper new ObjectMapper();
Car car new Car();
car.setBrand(“BMW”);
car.setDoors(4);
objectMapper.writeValue(
new FileOutputStream(“data/output-2.json”), car);
此示例首先创建一个ObjectMapper然后创建一个Car实例最后调用ObjectMapper的writeValue()方法该方法将Car对象转换为JSON并将其写入给定的FileOutputStream。
ObjectMapper的writeValueAsString()和writeValueAsBytes()都从一个对象生成JSON并将生成的JSON作为String或字节数组返回。 示例如下
ObjectMapper objectMapper new ObjectMapper();
Car car new Car();
car.setBrand(“宝马”);
car.setDoors(4);
String json objectMapper.writeValueAsString(car);
System.out.println(json);
运行结果 2、自定义序列化
有时想要将Java对象序列化为JSON的方式与使用Jackson的默认方式不同。 例如可能想要在JSON中使用与Java对象中不同的字段名称或者希望完全省略某些字段。
Jackson可以在ObjectMapper上设置自定义序列化器。 该序列化器已为某个类注册然后在每次要求ObjectMapper序列化Car对象时将调用该序列化器。
这是为Car类注册自定义序列化器的示例
CarSerializer carSerializer new CarSerializer(Car.class);
ObjectMapper objectMapper new ObjectMapper();
SimpleModule module
new SimpleModule(“CarSerializer”, new Version(2, 1, 3, null, null, null));
module.addSerializer(Car.class, carSerializer);
objectMapper.registerModule(module);
Car car new Car();
car.setBrand(“Mercedes”);
car.setDoors(5);
String carJson objectMapper.writeValueAsString(car);
自定义序列化器CarSerializer类
public class CarSerializer extends StdSerializer {
protected CarSerializer(Class t) {
super(t);
}
public void serialize(Car car, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider)
throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField(“producer”, car.getBrand());
jsonGenerator.writeNumberField(“doorCount”, car.getDoors());
jsonGenerator.writeEndObject();
}
}
运行结果 三、Jackson 日期转化 默认情况下Jackson会将java.util.Date对象序列化为其long型的值该值是自1970年1月1日以来的毫秒数。但是Jackson还支持将日期格式化为字符串。
1、Date–long
默认的Jackson日期格式该格式将Date序列化为自1970年1月1日以来的毫秒数long类型。
这是一个包含Date字段的Java类示例
private String type null;
private Date date null;
public Transaction() {
}
public Transaction(String type, Date date) {
this.type type;
this.date date;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type type;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date date;
}
就像使用其他Java对象进行序列化一样代码如下
Transaction transaction new Transaction(“transfer”, new Date());
ObjectMapper objectMapper new ObjectMapper();
String output objectMapper.writeValueAsString(transaction);
System.out.println(output);
运行结果 2、Date–String
日期的long序列化格式不符合人类的时间查看格式。 因此Jackson也支持文本日期格式。 可以通过在ObjectMapper上设置SimpleDateFormat来指定要使用的确切Jackson日期格式。 这是在Jackson的ObjectMapper上设置SimpleDateFormat的示例
Transaction transaction new Transaction(“transfer”, new Date());
ObjectMapper objectMapper new ObjectMapper();
SimpleDateFormat dateFormat new SimpleDateFormat(“yyyy-MM-dd”);
objectMapper.setDateFormat(dateFormat);
String output2 objectMapper.writeValueAsString(transaction);
System.out.println(output2);
运行结果 四、Jackson JSON 树模型 Jackson具有内置的树模型可用于表示JSON对象。 如果不知道接收到的JSON的格式或者由于某种原因而不能或者只是不想创建一个类来表示它那么就要用到Jackson的树模型。 如果需要在使用或转化JSON之前对其进行操作也需要被用到Jackson树模型。 所有这些情况在数据流场景中都很常见。
Jackson树模型由JsonNode类表示。 您可以使用Jackson ObjectMapper将JSON解析为JsonNode树模型就像使用您自己的类一样。
以下将展示如何使用Jackson ObjectMapper读写JsonNode实例。
1、Jackson Tree Model简单例子
下面是一个简单的例子
String carJson
“{ “brand” : “Mercedes”, “doors” : 5 }”;
ObjectMapper objectMapper new ObjectMapper();
try {
JsonNode jsonNode objectMapper.readValue(carJson, JsonNode.class);
} catch (IOException e) {
e.printStackTrace();
}
只需将JsonNode.class作为第二个参数传递给readValue()方法而不是本教程前面的示例中使用的Car.class就可以将JSON字符串解析为JsonNode对象而不是Car对象。 。
ObjectMapper类还具有一个特殊的readTree()方法该方法返回JsonNode。 这是使用ObjectMapper readTree()方法将JSON解析为JsonNode的示例
String carJson
“{ “brand” : “Mercedes”, “doors” : 5 }”;
ObjectMapper objectMapper new ObjectMapper();
try {
JsonNode jsonNode objectMapper.readTree(carJson);
} catch (IOException e) {
e.printStackTrace();
}
2、Jackson JsonNode类
通过JsonNode类可以以非常灵活和动态的方式将JSON作为Java对象导航。这里了解一些如何使用它的基础知识。
将JSON解析为JsonNode或JsonNode实例树后就可以浏览JsonNode树模型。 这是一个JsonNode示例显示了如何访问JSON字段数组和嵌套对象
String carJson
“{ “brand” : “Mercedes”, “doors” : 5,” “owners” : [“John”, “Jack”, “Jill”], “nestedObject” : { “field” : “value” } };
ObjectMapper objectMapper new ObjectMapper();
try {
JsonNode jsonNode objectMapper.readValue(carJson, JsonNode.class);
JsonNode brandNode jsonNode.get(“brand”);
String brand brandNode.asText();
System.out.println(brand brand);
JsonNode doorsNode jsonNode.get(“doors”);
int doors doorsNode.asInt();
System.out.println(doors doors);
JsonNode array jsonNode.get(“owners”);
JsonNode jsonNode array.get(0);
String john jsonNode.asText();
System.out.println(john john);
JsonNode child jsonNode.get(“nestedObject”);
JsonNode childField child.get(“field”);
String field childField.asText();
System.out.println(field field);
} catch (IOException e) {
e.printStackTrace();
}
请注意JSON字符串现在包含一个称为owners的数组字段和一个称为nestedObject的嵌套对象字段。
无论访问的是字段数组还是嵌套对象都可以使用JsonNode类的get()方法。 通过将字符串作为参数提供给get()方法可以访问JsonNode的字段。 如果JsonNode表示数组则需要将索引传递给get()方法。 索引指定要获取的数组元素。
3、Java对象–JsonNode
可以使用Jackson ObjectMapper将Java对象转换为JsonNode而JsonNode是转换后的Java对象的JSON表示形式。 可以通过Jackson ObjectMapper valueToTree()方法将Java对象转换为JsonNode。 这是一个使用ObjectMapper valueToTree()方法将Java对象转换为JsonNode的示例
ObjectMapper objectMapper new ObjectMapper();
Car car new Car();
car.brand “Cadillac”;
car.doors 4;
JsonNode carJsonNode objectMapper.valueToTree(car);
4、JsonNode–Java对象
可以使用Jackson ObjectMapper treeToValue()方法将JsonNode转换为Java对象。 这类似于使用Jackson Jackson的ObjectMapper将JSON字符串或其他来源解析为Java对象。 唯一的区别是JSON源是JsonNode。 这是一个使用Jackson ObjectMapper treeToValue()方法将JsonNode转换为Java对象的示例
ObjectMapper objectMapper new ObjectMapper();
String carJson “{ “brand” : “Mercedes”, “doors” : 5 }”;
JsonNode carJsonNode objectMapper.readTree(carJson);
Car car objectMapper.treeToValue(carJsonNode);
上面的示例有点“人为”因为我们首先将JSON字符串转换为JsonNode然后将JsonNode转换为Car对象。 显然如果我们有对原始JSON字符串的引用则最好将其直接转换为Car对象而无需先将其转换为JsonNode。
四、JsonNode Jackson JsonNode类com.fasterxml.jackson.databind.JsonNode是Jackson的JSON树形模型对象图模型。 Jackson可以将JSON读取到JsonNode实例中然后将JsonNode写入JSON。 因此这一节将说明如何将JSON反序列化为JsonNode以及将JsonNode序列化为JSON。 此Jackson JsonNode教程还将说明如何从头开始构建JsonNode对象图因此以后可以将它们序列化为JSON。
1、JsonNode vs ObjectNode Jackson JsonNode类是不可变的。 这意味着实际上不能直接构建JsonNode实例的对象图。 而是创建JsonNode子类ObjectNode的对象图。 作为JsonNode的子类可以在可以使用JsonNode的任何地方使用ObjectNode。
2、JSON–JsonNode 要使用Jackson将JSON读取到JsonNode中首先需要创建一个Jackson ObjectMapper实例。 在ObjectMapper实例上调用readTree()并将JSON源作为参数传递。 这是将JSON反序列化为JsonNode的示例
String json { “f1” : “v1” } ;
ObjectMapper objectMapper new ObjectMapper();
JsonNode jsonNode objectMapper.readTree(json);
System.out.println(jsonNode.get(“f1”).asText());
3、JsonNode–JSON 要将Jackson的JsonNode写入JSON还需要一个Jackson ObjectMapper实例。 在ObjectMapper上调用writeValueAsString()方法或任何适合需要的写入方法。 这是将JsonNode写入JSON的示例
ObjectMapper objectMapper new ObjectMapper();
JsonNode jsonNode readJsonIntoJsonNode();
String json objectMapper.writeValueAsString(jsonNode);
4、获取JsonNode字段 JsonNode可以像JSON对象一样具有字段。 假设已将以下JSON解析为JsonNode
{
“field1” : “value1”,
“field2” : 999
}
此JSON对象具有两个名为field1和field2的字段。 如果有一个表示上述JSON对象的Jackson JsonNode则可以这样获得两个字段
JsonNode jsonNode … //parse above JSON into a JsonNode
JsonNode field1 jsonNode.get(“field1”);
JsonNode field2 jsonNode.get(“field2”);
请注意即使两个字段都是String字段get()方法也始终返回JsonNode来表示该字段。
5、在路径中获取JsonNode字段 Jackson JsonNode有一个称为at()的特殊方法。 at()方法可以从JSON图中以给定JsonNode为根的任何位置访问JSON字段。 假设JSON结构如下所示
{
“identification” : {
“name” : “James”,
ssn: “ABC123552”
}
}
如果将此JSON解析为JsonNode则可以使用at()方法访问名称字段如下所示
JsonNode nameNode jsonNode.at(“/identification/name”);
注意传递给at()方法的参数字符串/ identification / name。 这是一个JSON路径表达式。 此路径表达式指定从根JsonNode到您要访问其值的字段的完整路径。 这类似于从文件系统根目录到Unix文件系统中文件的路径。
请注意JSON路径表达式必须以斜杠字符/字符开头。
at()方法返回一个JsonNode它表示请求的JSON字段。 要获取该字段的实际值需要调用下一部分介绍的方法之一。 如果没有节点与给定的路径表达式匹配则将返回null。
6、转换JsonNode字段 Jackson JsonNode类包含一组可以将字段值转换为另一种数据类型的方法。 例如将String字段值转换为long或相反。 这是将JsonNode字段转换为一些更常见的数据类型的示例
String f2Str jsonNode.get(“f2”).asText();
double f2Dbl jsonNode.get(“f2”).asDouble();
int f2Int jsonNode.get(“f2”).asInt();
long f2Lng jsonNode.get(“f2”).asLong();
使用默认值转换:
如果JsonNode中的字段可以为null则在尝试转换它时可以提供默认值。 这是使用默认值调用转换方法的示例
ObjectMapper objectMapper new ObjectMapper();
String json “{ “f1”:“Hello”, “f2”:null }”;
JsonNode jsonNode objectMapper.readTree(json);
String f2Value jsonNode.get(“f2”).asText(“Default”);
在示例的JSON字符串中可以看到声明了f2字段但将其设置为null。 在这种情况下调用jsonNode.get“ f2”。asText“ Default”将返回默认值在此示例中为字符串Default。
asDouble()asInt()和asLong()方法还可以采用默认参数值如果尝试从中获取值的字段为null则将返回默认参数值。
请注意如果该字段在JSON中未显式设置为null但在JSON中丢失则调用jsonNode.get“ fieldName”将返回Java null值您无法在该Java值上调用asInt() asDouble()asLong()或asText()。 如果尝试这样做将会导致NullPointerException。 这是说明这种情况的示例
ObjectMapper objectMapper new ObjectMapper();
String json “{ “f1”:“Hello” }”;
JsonNode jsonNode objectMapper.readTree(json);
JsonNode f2FieldNode jsonNode.get(“f2”);
7、创建一个ObjectNode 如前所述JsonNode类是不可变的。 要创建JsonNode对象图必须能够更改图中的JsonNode实例例如 设置属性值和子JsonNode实例等。由于是不可变的因此无法直接使用JsonNode来实现。
而是创建一个ObjectNode实例该实例是JsonNode的子类。 这是一个通过Jackson ObjectMapper createObjectNode()方法创建ObjectNode的示例
ObjectMapper objectMapper new ObjectMapper();
ObjectNode objectNode objectMapper.createObjectNode();
8、Set ObjectNode字段 要在Jackson ObjectNode上设置字段可以调用其set()方法并将字段名称String和JsonNode作为参数传递。 这是在Jackson的ObjectNode上设置字段的示例
ObjectMapper objectMapper new ObjectMapper();
ObjectNode parentNode objectMapper.createObjectNode();
JsonNode childNode readJsonIntoJsonNode();
parentNode.set(“child1”, childNode);
9、Put ObjectNode字段 ObjectNode类还具有一组方法可以直接为字段put(设置)值。 这比尝试将原始值转换为JsonNode并使用set()进行设置要容易得多。 以下是使用put()方法为ObjectNode上的字段设置字符串值的示例
objectNode.put(“field1”, “value1”);
objectNode.put(“field2”, 123);
objectNode.put(“field3”, 999.999);
10、删除字段 ObjectNode类具有一个称为remove()的方法该方法可用于从ObjectNode中删除字段。 这是一个通过其remove()方法从Jackson ObjectNode删除字段的示例
objectNode.remove(“fieldName”);
11、循环JsonNode字段 JsonNode类具有一个名为fieldNames()的方法该方法返回一个Iterator可以迭代JsonNode的所有字段名称。 我们可以使用字段名称来获取字段值。 这是一个迭代Jackson JsonNode的所有字段名称和值的示例
Iterator fieldNames jsonNode.fieldNames();
while(fieldNames.hasNext()) {
String fieldName fieldNames.next();
JsonNode field jsonNode.get(fieldName);
}
五、JsonParser Jackson JsonParser类是一个底层一些的JSON解析器。 它类似于XML的Java StAX解析器差别是JsonParser解析JSON而不解析XML。
Jackson JsonParser的运行层级低于Jackson ObjectMapper。 这使得JsonParser比ObjectMapper更快但使用起来也比较麻烦。
1、创建一个JsonParser 为了创建Jackson JsonParser首先需要创建一个JsonFactory。 JsonFactory用于创建JsonParser实例。 JsonFactory类包含几个createParser()方法每个方法都使用不同的JSON源作为参数。
这是创建一个JsonParser来从字符串中解析JSON的示例
String carJson
“{ “brand” : “Mercedes”, “doors” : 5 }”;
JsonFactory factory new JsonFactory();
JsonParser parser factory.createParser(carJson);
2、用JsonParser转化JSON 一旦创建了Jackson JsonParser就可以使用它来解析JSON。 JsonParser的工作方式是将JSON分解为一系列令牌可以一个一个地迭代令牌。
这是一个JsonParser示例它简单地循环遍历所有标记并将它们输出到System.out。 这是一个实际上很少用示例只是展示了将JSON分解成的令牌以及如何遍历令牌的基础知识。
tring carJson
“{ “brand” : “Mercedes”, “doors” : 5 }”;
JsonFactory factory new JsonFactory();
JsonParser parser factory.createParser(carJson);
while(!parser.isClosed()){
JsonToken jsonToken parser.nextToken();
System.out.println(jsonToken jsonToken);
}
只要JsonParser的isClosed()方法返回false那么JSON源中仍然会有更多的令牌。
可以使用JsonParser的nextToken()获得一个JsonToken。 您可以使用此JsonToken实例检查给定的令牌。 令牌类型由JsonToken类中的一组常量表示。 这些常量是
START_OBJECT
END_OBJECT
START_ARRAY
END_ARRAY
FIELD_NAME
VALUE_EMBEDDED_OBJECT
VALUE_FALSE
VALUE_TRUE
VALUE_NULL
VALUE_STRING
VALUE_NUMBER_INT
VALUE_NUMBER_FLOAT
可以使用这些常量来找出当前JsonToken是什么类型的令牌。 可以通过这些常量的equals()方法进行操作。 这是一个例子
String carJson
“{ “brand” : “Mercedes”, “doors” : 5 }”;
JsonFactory factory new JsonFactory();
JsonParser parser factory.createParser(carJson);
Car car new Car();
while(!parser.isClosed()){
JsonToken jsonToken parser.nextToken();
if(JsonToken.FIELD_NAME.equals(jsonToken)){
String fieldName parser.getCurrentName();
System.out.println(fieldName);
jsonToken parser.nextToken();
if(“brand”.equals(fieldName)){
car.brand parser.getValueAsString();
} else if (“doors”.equals(fieldName)){
car.doors parser.getValueAsInt();
}
}
}
System.out.println(car.brand car.brand);
System.out.println(car.doors car.doors);
如果指向的标记是字段名称则JsonParser的getCurrentName()方法将返回当前字段名称。
如果指向的令牌是字符串字段值则getValueAsString()返回当前令牌值作为字符串。 如果指向的令牌是整数字段值则getValueAsInt()返回当前令牌值作为int值。 JsonParser具有更多类似的方法来获取不同类型的curren令牌值例如booleanshortlongfloatdouble等。
六、JsonGenerator Jackson JsonGenerator用于从Java对象或代码从中生成JSON的任何数据结构生成JSON。
1、创建一个JsonGenerator 为了创建Jackson JsonGenerator必须首先创建JsonFactory实例。 这是创建JsonFactory的方法
JsonFactory factory new JsonFactory();
一旦创建了JsonFactory就可以使用JsonFactory的createGenerator()方法创建JsonGenerator。 这是创建JsonGenerator的示例
JsonFactory factory new JsonFactory();
JsonGenerator generator factory.createGenerator(
new File(“data/output.json”), JsonEncoding.UTF8);
createGenerator()方法的第一个参数是生成的JSON的目标。 在上面的示例中参数是File对象。 这意味着生成的JSON将被写入给定文件。 createGenerator()方法已重载因此还有其他版本的createGenerator()方法采用例如OutputStream等提供了有关将生成的JSON写入何处的不同选项。
createGenerator()方法的第二个参数是生成JSON时使用的字符编码。 上面的示例使用UTF-8。
2、使用JsonGenerator生成JSON 一旦创建了JsonGenerator就可以开始生成JSON。 JsonGenerator包含一组write …()方法可以使用这些方法来编写JSON对象的各个部分。 这是一个使用Jackson JsonGenerator生成JSON的简单示例
JsonFactory factory new JsonFactory();
JsonGenerator generator factory.createGenerator(
new File(“data/output.json”), JsonEncoding.UTF8);
generator.writeStartObject();
generator.writeStringField(“brand”, “Mercedes”);
generator.writeNumberField(“doors”, 5);
generator.writeEndObject();
generator.close();
此示例首先调用writeStartObject()将{写入输出。 然后该示例调用writeStringField()将品牌字段名称值写入输出。 之后将调用writeNumberField()方法此方法会将Doors字段名称值写入输出。 最后调用writeEndObject()将}写入输出。
JsonGenerator还可以使用许多其他写入方法。 这个例子只显示了其中一些。
3、关闭JsonGenerator 完成生成JSON后应关闭JsonGenerator。 您可以通过调用其close()方法来实现。 这是关闭JsonGenerator的样子
generator.close();
七、Jackson注解 Jackson JSON工具包包含一组Java注解可以使用这些注解来设置将JSON读入对象的方式或从对象生成什么JSON的方式。 此Jackson注解教程介绍了如何使用Jackson的注解。
下面是一些常用的注解
| 注解 | 用法 |
| — | — |
| JsonProperty | 用于属性把属性的名称序列化时转换为另外一个名称。示例
JsonProperty(“birth_ d ate”)
private Date birthDate; |
| JsonFormat | 用于属性或者方法把属性的格式序列化时转换成指定的格式。示例
JsonFormat(timezone “GMT8”, pattern “yyyy-MM-dd HH:mm”)
public Date getBirthDate() |
| JsonPropertyOrder | 用于类 指定属性在序列化时 json 中的顺序 示例
JsonPropertyOrder({ “birth_Date”, “name” })
public class Person |
| JsonCreator | 用于构造方法和 JsonProperty 配合使用适用有参数的构造方法。 示例
JsonCreator
public Person(JsonProperty(“name”)String name) {…} |
| JsonAnySetter | 用于属性或者方法设置未反序列化的属性名和值作为键值存储到 map 中
JsonAnySetter
public void set(String key, Object value) {
map.put(key, value);
} |
| JsonAnyGetter | 用于方法 获取所有未序列化的属性
public MapString, Object any() { return map; } |
下面是一些注解的详细说明。
一、Read Write注解 Jackson包含一组注解这些注解会影响从JSON读取Java对象以及将Java对象写入JSON。 我将这些注解称为“读写注解”。 以下各节将更详细地介绍Jackson的读写注解。
1、JsonIgnore
Jackson注解JsonIgnore用于告诉Jackson忽略Java对象的某个属性字段。 在将JSON读取到Java对象中以及将Java对象写入JSON时都将忽略该属性。
这是使用JsonIgnore注解的示例
import com.fasterxml.jackson.annotation.JsonIgnore;
public class PersonIgnore {
JsonIgnore
public long personId 0;
public String name null;
}
在上面的类中不会从JSON读取或写入JSON属性personId。
2、JsonIgnoreProperties
JsonIgnoreProperties Jackson注解用于指定要忽略的类的属性列表。 JsonIgnoreProperties注解放置在类声明上方而不是要忽略的各个属性字段上方。
这是如何使用JsonIgnoreProperties注解的示例
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
JsonIgnoreProperties({“firstName”, “lastName”})
public class PersonIgnoreProperties {
public long personId 0;
public String firstName null;
public String lastName null;
}
在此示例中属性firstName和lastName都将被忽略因为它们的名称在类声明上方的JsonIgnoreProperties注解声明内列出。
3、JsonIgnoreType
JsonIgnoreType Jackson注解用于将整个类型类标记为在使用该类型的任何地方都将被忽略。
这是一个示例展示如何使用JsonIgnoreType注解
import com.fasterxml.jackson.annotation.JsonIgnoreType;
public class PersonIgnoreType {
JsonIgnoreType
public static class Address {
public String streetName null;
public String houseNumber null;
public String zipCode null;
public String city null;
public String country null;
}
public long personId 0;
public String name null;
public Address address null;
}
在上面的示例中所有Address实例将被忽略。
4、JsonAutoDetect
Jackson注解JsonAutoDetect用于告诉Jackson在读写对象时包括非public修饰的属性。
这是一个示例类展示如何使用JsonAutoDetect注解
import com.fasterxml.jackson.annotation.JsonAutoDetect;
JsonAutoDetect(fieldVisibility JsonAutoDetect.Visibility.ANY )
public class PersonAutoDetect {
private long personId 123;
public String name null;
}
JsonAutoDetect.Visibility类包含与Java中的可见性级别匹配的常量表示ANYDEFAULTNON_PRIVATENONEPROTECTED_AND_PRIVATE和PUBLIC_ONLY。
二、Read注解 Jackson包含一组注解这些注解仅影响Jackson将JSON解析为对象的方式-意味着它们影响Jackson对JSON的读取。 我称这些为“读注解”。 以下各节介绍了Jackson的读注解。
1、JsonSetter
Jackson注解JsonSetter用于告诉Jackson当将JSON读入对象时应将此setter方法的名称与JSON数据中的属性名称匹配。 如果Java类内部使用的属性名称与JSON文件中使用的属性名称不同这个注解就很有用了。
以下Person类用personId名称对应JSON中名为id的字段
public class Person {
private long personId 0;
private String name null;
public long getPersonId() { return this.personId; }
public void setPersonId(long personId) { this.personId personId; }
public String getName() { return name; }
public void setName(String name) { this.name name; }
}
但是在此JSON对象中使用名称id代替personId
{
“id” : 1234,
“name” : “John”
}
Jackson无法将id属性从JSON对象映射到Java类的personId字段。
JsonSetter注解指示Jackson为给定的JSON字段使用setter方法。 在我们的示例中我们在setPersonId()方法上方添加JsonSetter注解。
这是添加JsonSetter注解的实例
public class Person {
private long personId 0;
private String name null;
public long getPersonId() { return this.personId; }
JsonSetter(“id”)
public void setPersonId(long personId) { this.personId personId; }
public String getName() { return name; }
public void setName(String name) { this.name name; }
}
JsonSetter注解中指定的值是要与此setter方法匹配的JSON字段的名称。 在这种情况下名称为id因为这是我们要映射到setPersonId()setter方法的JSON对象中字段的名称。
2、JsonAnySetter
Jackson注解JsonAnySetter表示Jackson为JSON对象中所有无法识别的字段调用相同的setter方法。 “无法识别”是指尚未映射到Java对象中的属性或设置方法的所有字段。
看一下这个Bag类
public class Bag {
private MapString, Object properties new HashMap();
public void set(String fieldName, Object value){
this.properties.put(fieldName, value);
}
public Object get(String fieldName){
return this.properties.get(fieldName);
}
}
然后查看此JSON对象
{
“id” : 1234,
“name” : “John”
}
Jackson无法直接将此JSON对象的id和name属性映射到Bag类因为Bag类不包含任何公共字段或setter方法。
可以通过添加JsonAnySetter注解来告诉Jackson为所有无法识别的字段调用set()方法如下所示
public class Bag {
private MapString, Object properties new HashMap();
JsonAnySetter
public void set(String fieldName, Object value){
this.properties.put(fieldName, value);
}
public Object get(String fieldName){
return this.properties.get(fieldName);
}
}
现在Jackson将使用JSON对象中所有无法识别的字段的名称和值调用set()方法。
请记住这仅对无法识别的字段有效。 例如如果您向Bag Java类添加了公共名称属性或setNameString方法则JSON对象中的名称字段将改为映射到该属性/设置器。
3、JsonCreator
Jackson注解JsonCreator用于告诉Jackson该Java对象具有一个构造函数“创建者”该构造函数可以将JSON对象的字段与Java对象的字段进行匹配。
JsonCreator注解在无法使用JsonSetter注解的情况下很有用。 例如不可变对象没有任何设置方法因此它们需要将其初始值注入到构造函数中。
以这个PersonImmutable类为例
public class PersonImmutable {
private long id 0;
private String name null;
public PersonImmutable(long id, String name) {
this.id id;
this.name name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
}
要告诉Jackson应该调用PersonImmutable的构造函数我们必须在构造函数中添加JsonCreator注解。 但是仅凭这一点还不够。 我们还必须注解构造函数的参数以告诉Jackson将JSON对象中的哪些字段传递给哪些构造函数参数。
添加了JsonCreator和JsonProperty注解的PersonImmutable类的示例如下
public class PersonImmutable {
private long id 0;
private String name null;
JsonCreator
public PersonImmutable(
JsonProperty(“id”) long id,
JsonProperty(“name”) String name ) {
this.id id;
this.name name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
}
请注意构造函数上方的注解以及构造函数参数之前的注解。 现在Jackson能够从此JSON对象创建PersonImmutable
{
“id” : 1234,
“name” : “John”
}
4、JacksonInject
Jackson注解JacksonInject用于将值注入到解析的对象中而不是从JSON中读取这些值。 例如假设正在从各种不同的源下载Person JSON对象并且想知道给定Person对象来自哪个源。 源本身可能不包含该信息但是可以让Jackson将其注入到根据JSON对象创建的Java对象中。
要将Java类中的字段标记为需要由Jackson注入其值的字段请在该字段上方添加JacksonInject注解。
这是一个示例PersonInject类在属性上方添加了JacksonInject注解
public class PersonInject {
public long id 0;
public String name null;
JacksonInject
public String source null;
}
为了让Jackson将值注入属性需要在创建Jackson ObjectMapper时做一些额外的工作。
这是让Jackson将值注入Java对象的过程
InjectableValues inject new InjectableValues.Std().addValue(String.class, “jenkov.com”);
PersonInject personInject new ObjectMapper().reader(inject)
.forType(PersonInject.class)
.readValue(new File(“data/person.json”));
请注意如何在InjectableValues addValue()方法中设置要注入到source属性中的值。 还要注意该值仅绑定到字符串类型-而不绑定到任何特定的字段名称。 JacksonInject注解指定将值注入到哪个字段。
如果要从多个源下载人员JSON对象并为每个源注入不同的源值则必须为每个源重复以上代码。
5、JsonDeserialize
Jackson注解JsonDeserialize用于为Java对象中给定的属性指定自定义反序列化器类。
例如假设想优化布尔值false和true的在线格式使其分别为0和1。
首先需要将JsonDeserialize注解添加到要为其使用自定义反序列化器的字段。 这是将JsonDeserialize注解添加到字段的示例
public class PersonDeserialize {
public long id 0;
public String name null;
JsonDeserialize(using OptimizedBooleanDeserializer.class)
public boolean enabled false;
}
其次这是JsonDeserialize注解中引用的OptimizedBooleanDeserializer类的实例
public class OptimizedBooleanDeserializer
extends JsonDeserializer {
Override
public Boolean deserialize(JsonParser jsonParser,
DeserializationContext deserializationContext) throws
IOException, JsonProcessingException {
String text jsonParser.getText();
if(“0”.equals(text)) return false;
return true;
}
}
请注意OptimizedBooleanDeserializer类使用通用类型Boolean扩展了JsonDeserializer。 这样做会使deserialize()方法返回一个布尔对象。 如果要反序列化其他类型例如java.util.Date则必须在泛型括号内指定该类型。
可以通过调用jsonParser参数的getText()方法来获取要反序列化的字段的值。 然后可以将该文本反序列化为任何值然后输入反序列化程序所针对的类型在此示例中为布尔值。
最后需要查看使用自定义反序列化器和JsonDeserializer注解反序列化对象的格式
PersonDeserialize person objectMapper
.reader(PersonDeserialize.class)
.readValue(new File(“data/person-optimized-boolean.json”));
注意我们首先需要如何使用ObjectMapper的reader()方法为PersonDeserialize类创建一个阅读器然后在该方法返回的对象上调用readValue()。
三、Write注解 Jackson还包含一组注解这些注解可以影响Jackson将Java对象序列化写入到JSON的方式。 以下各节将介绍这些写序列化注解中的每一个。
1、JsonInclude
Jackson注解JsonInclude告诉Jackson仅在某些情况下包括属性。 例如仅当属性为非null非空或具有非默认值时才应包括该属性。 这是显示如何使用JsonInclude注解的示例
import com.fasterxml.jackson.annotation.JsonInclude;
JsonInclude(JsonInclude.Include.NON_EMPTY)
public class PersonInclude {
public long personId 0;
public String name null;
}
如果为该示例设置的值是非空的则此示例将仅包括name属性这意味着不为null且不是空字符串。
JsonInclude注解的一个更通俗的名称应该是JsonIncludeOnlyWhen但是写起来会更长。
2、JsonGetter
JsonGetter Jackson注解用于告诉Jackson应该通过调用getter方法而不是通过直接字段访问来获取某个字段值。 如果您的Java类使用jQuery样式的getter和setter名称则JsonGetter注解很有用。
例如您可能拥有方法personId()和personIdlong id而不是getPersonId()和setPersonId()。
这是一个名为PersonGetter的示例类它显示了JsonGetter注解的用法
public class PersonGetter {
private long personId 0;
JsonGetter(“id”)
public long personId() { return this.personId; }
JsonSetter(“id”)
public void personId(long personId) { this.personId personId; }
}
最后
自我介绍一下小编13年上海交大毕业曾经在小公司待过也去过华为、OPPO等大厂18年进入阿里一直到现在。
深知大多数Java工程师想要提升技能往往是自己摸索成长自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》初衷也很简单就是希望能够帮助到想自学提升又不知道该从何学起的朋友同时减轻大家的负担。 既有适合小白学习的零基础资料也有适合3年以上经验的小伙伴深入学习提升的进阶课程基本涵盖了95%以上Java开发知识点不论你是刚入门Java开发的新手还是希望在技术上不断提升的资深开发者这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助需要这份全套学习资料的朋友可以戳我获取
由于文件比较大这里只是将部分目录截图出来每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频并且会持续更新 eption {
String text jsonParser.getText();
if(“0”.equals(text)) return false;
return true;
}
}
请注意OptimizedBooleanDeserializer类使用通用类型Boolean扩展了JsonDeserializer。 这样做会使deserialize()方法返回一个布尔对象。 如果要反序列化其他类型例如java.util.Date则必须在泛型括号内指定该类型。
可以通过调用jsonParser参数的getText()方法来获取要反序列化的字段的值。 然后可以将该文本反序列化为任何值然后输入反序列化程序所针对的类型在此示例中为布尔值。
最后需要查看使用自定义反序列化器和JsonDeserializer注解反序列化对象的格式
PersonDeserialize person objectMapper
.reader(PersonDeserialize.class)
.readValue(new File(“data/person-optimized-boolean.json”));
注意我们首先需要如何使用ObjectMapper的reader()方法为PersonDeserialize类创建一个阅读器然后在该方法返回的对象上调用readValue()。
三、Write注解 Jackson还包含一组注解这些注解可以影响Jackson将Java对象序列化写入到JSON的方式。 以下各节将介绍这些写序列化注解中的每一个。
1、JsonInclude
Jackson注解JsonInclude告诉Jackson仅在某些情况下包括属性。 例如仅当属性为非null非空或具有非默认值时才应包括该属性。 这是显示如何使用JsonInclude注解的示例
import com.fasterxml.jackson.annotation.JsonInclude;
JsonInclude(JsonInclude.Include.NON_EMPTY)
public class PersonInclude {
public long personId 0;
public String name null;
}
如果为该示例设置的值是非空的则此示例将仅包括name属性这意味着不为null且不是空字符串。
JsonInclude注解的一个更通俗的名称应该是JsonIncludeOnlyWhen但是写起来会更长。
2、JsonGetter
JsonGetter Jackson注解用于告诉Jackson应该通过调用getter方法而不是通过直接字段访问来获取某个字段值。 如果您的Java类使用jQuery样式的getter和setter名称则JsonGetter注解很有用。
例如您可能拥有方法personId()和personIdlong id而不是getPersonId()和setPersonId()。
这是一个名为PersonGetter的示例类它显示了JsonGetter注解的用法
public class PersonGetter {
private long personId 0;
JsonGetter(“id”)
public long personId() { return this.personId; }
JsonSetter(“id”)
public void personId(long personId) { this.personId personId; }
}
最后
自我介绍一下小编13年上海交大毕业曾经在小公司待过也去过华为、OPPO等大厂18年进入阿里一直到现在。
深知大多数Java工程师想要提升技能往往是自己摸索成长自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Java开发全套学习资料》初衷也很简单就是希望能够帮助到想自学提升又不知道该从何学起的朋友同时减轻大家的负担。
[外链图片转存中…(img-59gq63Kq-1715698045074)]
[外链图片转存中…(img-CH1hPO68-1715698045075)]
[外链图片转存中…(img-wleg54Qk-1715698045075)]
既有适合小白学习的零基础资料也有适合3年以上经验的小伙伴深入学习提升的进阶课程基本涵盖了95%以上Java开发知识点不论你是刚入门Java开发的新手还是希望在技术上不断提升的资深开发者这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助需要这份全套学习资料的朋友可以戳我获取
由于文件比较大这里只是将部分目录截图出来每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频并且会持续更新