在想要攀登到科学顶峰之前,务必把科学的初步知识研究透彻。还没有充分领会前面的东西时,就决不要动手搞往后的事情。
Spring
Bean与Component @Component(@Controller @Service @Respository) :Class
表明该类会作为组件类,告知Spring容器为该类创建bean(通过类路径扫描自动装配到Spring容器中)。
通过组件扫描,Spring将扫描整个类路径,并将所有@Component注释类添加到Spring Context。Component会把整个类当成bean注册到Spring容器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 public class User { private String name; private Integer id; public User () { } public User (String name, Integer id) { this .name = name; this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public Integer getId () { return id; } public void setId (Integer id) { this .id = id; } @Override public String toString () { return "User{" + "name='" + name + '\'' + ", id=" + id + '}' ; } }
Dao层
1 2 3 4 5 public interface UserDao { int addUser (User user) ; int deleteUserById (int id) ; User selectUserByID (int id) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Repository public class UserDaoImpl implements UserDao { @Override public int addUser (User user) { System.out.println("->UserDaoImpl:addUser" ); return 1 ; } @Override public int deleteUserById (int id) { System.out.println("->UserDaoImpl:deleteUser" ); return 1 ; } @Override public User selectUserByID (int id) { System.out.println("->UserDaoImpl:selectUserByID" ); return new User("tester" ,1 ); } }
Service层
1 2 3 4 5 public interface UserService { int addUser (User user) ; int deleteUserById (int id) ; User selectUserByID (int id) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Service @Primary public class UserServiceImpl1 implements UserService { @Autowired UserDao userDao; @Override public int addUser (User user) { return userDao.addUser(user); } @Override public int deleteUserById (int id) { return userDao.deleteUserById(id); } @Override public User selectUserByID (int id) { System.out.print("===UserServiceImpl1:" ); return userDao.selectUserByID(id); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Service public class UserServiceImpl2 implements UserService { @Autowired UserDao userDao; @Override public int addUser (User user) { return userDao.addUser(user); } @Override public int deleteUserById (int id) { return userDao.deleteUserById(id); } @Override public User selectUserByID (int id) { System.out.print("===UserServiceImpl2:" ); return userDao.selectUserByID(id); } }
测试
1 2 3 4 5 6 7 8 9 10 11 @SpringBootTest class MyApplicationTests { @Autowired UserService userService; @Test public void test () { userService.selectUserByID(1 ); } }
1 2 3 4 @Service @Qualifier("userServiceImpl1") public class UserServiceImpl1 implements UserService {}
1 2 3 4 @Service @Qualifier("userServiceImpl2") public class UserServiceImpl2 implements UserService {}
1 2 3 @Autowired @Qualifier("userServiceImpl1") UserService userService;
@Autowired自动装配:根据UserDao的类型寻找对应的bean,此处即为UserDao注册在Spring容器中的两个对应的实现类UserServiceImpl1和UserServiceImpl2(虽然定义属性是接口类型,但最终装配时是对应的实现类)。当该接口具有多个实现类,需要在@Autowired自动装配时使用@Primary(在实现类上使用,即优先选择)或者@Qualifier进行指定一个实现类进行注入。
@Bean :Method
表明该方法将会返回一个对象,该对象会注册为Spring应用上下文的bean。通常该方法定义产生bean实例的逻辑。
更加灵活,可以独立加在方法上(Bean的声明与类定义分离),按需注册到Spring容器,当需要用到第三方类库里面某个方法,可以用@Bean把这个方法注册到Spring容器。
需要在配置类中使用,即类上需用@Configuration注解。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 public class MyBean { private String myBeanName; @Value("1") private Integer myBeanId; public String getMyBeanName () { return myBeanName; } public void setMyBeanName (String myBeanName) { this .myBeanName = myBeanName; } public Integer getMyBeanId () { return myBeanId; } public void setMyBeanId (Integer myBeanId) { this .myBeanId = myBeanId; } @Override public String toString () { return "MyBean{" + "myBeanName='" + myBeanName + '\'' + ", myBeanId=" + myBeanId + '}' ; } }
1 2 3 4 5 6 7 8 9 10 @Configuration public class AppConfig { @Bean public MyBean myBean () { MyBean myBean = new MyBean(); myBean.setMyBeanName("MyFirstBean" ); return myBean; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @SpringBootTest class MyBeanApplicationTests { @Autowired MyBean myBean2; @Test public void testMyBean () { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); Object myBean1 = context.getBean("myBean" ); System.out.println(myBean1); MyBean myFirstBean = (MyBean)myBean1; System.out.println(myFirstBean.getMyBeanName()); } @Test public void testMyBean2 () { System.out.println(myBean2.toString()); } }
二者都可以通过@Autowired装配
@Component
and Further Stereotype Annotations
The @Repository
annotation is a marker for any class that fulfills the role or stereotype of a repository (also known as Data Access Object or DAO). Among the uses of this marker is the automatic translation of exceptions, as described in Exception Translation .
Spring provides further stereotype annotations: @Component
, @Service
, and @Controller
. @Component
is a generic stereotype for any Spring-managed component. @Repository
, @Service
, and @Controller
are specializations of @Component
for more specific use cases (in the persistence, service, and presentation layers, respectively). Therefore, you can annotate your component classes with @Component
, but, by annotating them with @Repository
, @Service
, or @Controller
instead, your classes are more properly suited for processing by tools or associating with aspects. For example, these stereotype annotations make ideal targets for pointcuts. @Repository
, @Service
, and @Controller
can also carry additional semantics in future releases of the Spring Framework. Thus, if you are choosing between using @Component
or @Service
for your service layer, @Service
is clearly the better choice. Similarly, as stated earlier, @Repository
is already supported as a marker for automatic exception translation in your persistence layer.
Annotation
Meaning
Scope
@Component
generic stereotype for any Spring-managed component
组件类
@Repository
stereotype for persistence layer
数据库操作、数据传至Service(@Service)层
@Service
stereotype for service layer
业务逻辑、数据处理、调用持久层(Persistence layer/Data Access Layer @Repository)方法等
@Controller
stereotype for presentation layer (spring-mvc)
处理请求(调度、转发、调用Service(@Service层)方法等)
Java JSON Jackson Jackson
Jackson是当前用的比较广泛的,用来序列化和反序列化 json 的Java开源框架,是Spring MVC 默认json 解析器。
特点:
依赖关系较少
解析大json文件速度较快
占用内存比较低,性能比较好
易于使用
Fastjson FastJSON
fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。
特点:
Gson Gson
Gson使用指南
Gson (Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。
Gson当初是为因应Google公司内部需求而由Google自行研发而来,但自从在2008年五月公开发布第一版后已被许多公司或用户应用。
Spring与Gson
如果使用Gson作为默认库,需要从classpath
中删除Jackson
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <dependencies > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > <exclusions > <exclusion > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-json</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > com.google.code.gson</groupId > <artifactId > gson</artifactId > <version > 2.9.0</version > </dependency > </dependencies >
1 2 3 4 5 6 7 @SpringBootApplication(exclude = {JacksonAutoConfiguration.class}) public class GsonSpringBootApplication { public static void main (String[] args) { SpringApplication.run(GsonSpringBootApplication.class, args); } }
使用HttpMessageConverters自定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @Configuration public class ApplicationConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters (List<HttpMessageConverter<?>> converters) { converters.add(customGsonHttpMessageConverter()); super .configureMessageConverters(converters); } private GsonHttpMessageConverter customGsonHttpMessageConverter () { Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'" ) .create(); GsonHttpMessageConverter gsonMessageConverter = new GsonHttpMessageConverter(); gsonMessageConverter.setGson(gson); return gsonMessageConverter; } }
1.Gson基本用法
Gson提供fromJson()
和toJson()
两个方法用于反序列化和序列化。
Gson.toJson(Object)
Gson.fromJson(String,Class)
Gson.fromJson(String,Type)
反序列化
1 2 3 4 5 Gson gson = new Gson(); int i = gson.fromJson("100" , int .class); double aDouble = gson.fromJson("99.99" , double .class); boolean aBoolean = gson.fromJson("true" , boolean .class); String aString = gson.fromJson("String" , String.class);
1 2 3 4 5 6 7 8 @Data @AllArgsConstructor @NoArgsConstructor public class Product { private String id; private String name; private Double price; }
1 2 3 Gson gson = new Gson(); Product sugar_box = new Product("20210103" , "Sugar Box" , 15.69 ); String jsonString = gson.toJson(sugar_box);
序列化
1 2 3 4 Gson gson = new Gson(); String jsonNumber = gson.toJson(100 ); String jsonBoolean = gson.toJson(false ); String jsonString = gson.toJson("String" );
1 2 3 Gson gson = new Gson(); String jsonString1 = "{\"id\":\"20210103\",\"name\":\"Sugar Box\",\"price\":15.69}" ; Product sugar_box = gson.fromJson(jsonString1,Product.class);
2.@SerializedName
@SerializedName:属性重命名,可以将json中的属性名转换为自定义的属性名(原属性名失效)
value
:json属性名
alternate
:(备选属性名)接收一个String数组alternate数组中出现任意一个属性名都可以转换为自定义的属性,如果出现多个则以最后一个为准
1 2 @SerializedName("box_price") private Double price;
1 2 3 4 5 6 7 8 9 Gson gson = new Gson(); String jsonStr1 = "{\"id\":\"20090804\",\"name\":\"Wooden Box\",\"box_price\":16.69}" ; String jsonStr2 = "{\"id\":\"20190412\",\"name\":\"Iron Box\",\"price\":16.69}" ; Product woodenBox = gson.fromJson(jsonStr1,Product.class); Product ironBox = gson.fromJson(jsonStr2,Product.class);
1 2 @SerializedName(value = "price",alternate = {"box_price","chest_price"}) private Double price;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Gson gson = new Gson(); String jsonStr1 = "{\"id\":\"20090804\",\"name\":\"Wooden Box\",\"box_price\":15.34}" ; String jsonStr2 = "{\"id\":\"20190412\",\"name\":\"Case Box\",\"chest_price\":17.56}" ; String jsonStr3 = "{\"id\":\"20200916\",\"name\":\"Iron Box\",\"price\":16.69}" ; String jsonStr4 = "{\"id\":\"20050412\",\"name\":\"Box\",\"price\":16.6,\"box_price\":1.69,\"chest_price\":0.69}" ; Product woodenBox = gson.fromJson(jsonStr1,Product.class); Product caseBox = gson.fromJson(jsonStr2,Product.class); Product ironBox = gson.fromJson(jsonStr3,Product.class); Product box = gson.fromJson(jsonStr4,Product.class);
1 2 3 4 5 6 7 8 Gson gson = new Gson(); String jsonArray = "[\"Kotlin\",\"Groovy\",\"Scala\"]" ; String[] strings = gson.fromJson(jsonArray, String[].class); List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>(){}.getType()); for (String str:strings){ System.out.println(str); } System.out.println(stringList.toString());
3.泛型
1 2 3 4 5 6 7 8 9 Gson gson = new Gson(); String jsonArray = "[\"Kotlin\",\"Groovy\",\"Scala\"]" ; String[] strings = gson.fromJson(jsonArray, String[].class); List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>(){}.getType()); for (String str:strings){ System.out.println(str); } System.out.println(stringList.toString());
1 2 3 4 5 6 7 @Data @AllArgsConstructor @NoArgsConstructor public class User { private String name; private Integer age; }
1 2 3 4 5 6 7 @ToString public class Result <T > { public int code; public String message; public T data; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Gson gson = new Gson(); Type userType = new TypeToken<Result<User>>(){}.getType(); Type userListType = new TypeToken<Result<List<User>>>(){}.getType(); String json = "{\"code\":\"200\",\"message\":\"success\",\"data\":{\"name\":\"Zha\",\"age\":12}}" ; String jsonList = "{\"code\":\"404\",\"message\":\"Resource not found\",\"data\":[{\"name\":\"Li\",\"age\":19},{\"name\":\"Wu\",\"age\":25},{\"name\":\"Fu\",\"age\":35}]}" ; Result<User> userResult = gson.fromJson(json,userType); Result<List<User>> userListResult = gson.fromJson(jsonList,userListType); List<User> users = userListResult.data; System.out.println(userResult);
4.流式序列化和流式反序列化
1.流式序列化
自动流式反序列化(Gson.fromJson(Reader,Class)
Gson.fromJson(Reader,Type)
)
1 2 3 4 5 6 7 Gson gson = new Gson(); try (Reader reader = new FileReader("C:\\pro\\user.json" )) { User user = gson.fromJson(reader, User.class); System.out.println(user); } catch (IOException e) { e.printStackTrace(); }
Gson提供了Stream
包的JsonReader
类来手动实现反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 String json = "{\"name\":\"Zoom\",\"age\":\"24\"}" ; User user = new User(); JsonReader reader = new JsonReader(new StringReader(json)); reader.beginObject(); while (reader.hasNext()) { String str = reader.nextName(); switch (str) { case "name" : user.setName(reader.nextString()); break ; case "age" : user.setAge(reader.nextInt()); break ; } } reader.endObject();
2.流式序列化
自动流式序列化
toJson(Object src, Appendable writer)
toJson(Object src, Type typeOfSrc, Appendable writer)
toJson(JsonElement jsonElement, Appendable writer)
Appendable
接口:PrintStream
(System.out) StringBuilder
StringBuffer
和 *Writer
1 2 3 4 5 6 7 8 Gson gson = new Gson(); User user = new User("Pot" ,78 ); gson.toJson(user,System.out);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out)); writer.beginObject() .name("name" ).value("Nike" ) .name("age" ).value(11 ) .name("email" ).nullValue() .endObject(); writer.flush(); writer.beginArray() .value("Nike" ) .value(11 ) .nullValue() .endArray(); writer.flush();
5.GsonBuilder :构建Gson实例的类
1 2 Gson gson = new GsonBuilder() .create();
1 2 3 4 5 Gson gson = new Gson(); System.out.println(gson.toJson(new User("Korie" ,67 ))); Gson gson = new GsonBuilder().serializeNulls().create(); System.out.println(gson.toJson(new User("Korie" ,67 )));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Gson gson = new GsonBuilder() .serializeNulls() .setDateFormat("yyyy-MM-dd" ) .disableInnerClassSerialization() .generateNonExecutableJson() .disableHtmlEscaping() .setPrettyPrinting() .create();
5.字段过滤
1 2 3 4 5 6 public class User { private String name; private Integer age; private String email; private Boolean isDeveloper; }
1.@Expose
@Expose
注解提供了两个属性:
deserialize:默认为true(反序列化生效)
serialize:默认为true(序列化生效)
需要和GsonBuilder
使用,需要导出的字段上加上@Expose注解,不导出的字段不加。
1 2 3 4 5 6 7 8 9 10 public class User { @Expose private String name; @Expose private Integer age; @Expose private String email; @Expose(deserialize = true,serialize = false) private Boolean isDeveloper; }
1 2 3 4 5 6 7 User user = new User("RIOT" ,22 ,"TestLib@gmail.com" ,true ); String ustr = "{\"name\":\"Rich\",\"age\":26,\"email\":\"TestLib2@gmail.com\",\"isDeveloper\":\"false\"}" ; Gson gson = new GsonBuilder() .excludeFieldsWithoutExposeAnnotation() .create(); System.out.println(gson.toJson(user)); System.out.println(gson.fromJson(ustr,User.class));
2.@Since
和@Until
对基于版本的字段导出提供@Since
和@Until
注解,和GsonBuilder.setVersion(Double)配合使用。当前版本(GsonBuilder设置版本) 大于等于Since的值时该字段导出,小于Until的值时该字段导出。
当一个字段被@Since
和@Until
同时注解时,需同时满足条件。
1 2 3 4 5 6 public class SinceUntilSample { @Since(4) private String since; @Until(5) private String until; }
1 2 3 4 5 SinceUntilSample sinceUntilSample = new SinceUntilSample("since" ,"until" ); Gson gson = new GsonBuilder() .setVersion(3.9 ) .create(); System.out.println(gson.toJson(sinceUntilSample));
3.访问修饰符
GsonBuilder 提供 excludeFieldsWithModifiers
方法,可自定义可忽略类型,参数为java.lang.reflect.Modifier
类属性
1 2 3 4 5 6 7 8 public class ModifierSample { final String finalField = "final" ; static String staticField = "static" ; public String publicField = "public" ; protected String protectedField = "protected" ; String defaultField = "default" ; private String privateField = "private" ; }
1 2 3 4 5 6 7 8 9 ModifierSample modifierSample = new ModifierSample(); Gson gson = new GsonBuilder() .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC,Modifier.PUBLIC, Modifier.PROTECTED,Modifier.PRIVATE) .create(); System.out.println(gson.toJson(modifierSample));
4.自定义过滤规则
GsonBuilderde
的addSerializationExclusionStrategy
和addDeserializationExclusionStrategy
分别用于序列化和反序化(Gson提供的ExclusionStrategy接口)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ModifierSample modifierSample = new ModifierSample(); Gson gson = new GsonBuilder() .addSerializationExclusionStrategy(new ExclusionStrategy() { @Override public boolean shouldSkipField (FieldAttributes f) { if ("publicField" .equals(f.getName())) return true ; Expose expose = f.getAnnotation(Expose.class); if (expose != null && expose.deserialize() == false ) return true ; return false ; } @Override public boolean shouldSkipClass (Class<?> clazz) { return (clazz == int .class || clazz == Integer.class); } }) .create();
6.字段映射规则
1.GsonBuilder
FieldNamingStrategy
setFieldNamingPolicy
setFieldNamingStrategy
2.@SerializedName 注解拥有最高优先级,有 @SerializedName
注解字段上 FieldNamingStrategy
无法生效。
2.GsonBuilder.setFieldNamingPolicy
方法与枚举类FieldNamingPolicy
配合使用。
FieldNamingPolicy
结果
IDENTITY
原格式
UPPER_CAMEL_CASE
首个字母大写
UPPER_CAMEL_CASE_WITH_SPACES
空格隔开
LOWER_CASE_WITH_UNDERSCORES
下划线隔开
LOWER_CASE_WITH_DASHES
中间线隔开
LOWER_CASE_WITH_DOTS
点号隔开
1 2 3 4 5 public class User { private String name; private Integer age; private String emailAddress; }
1 2 3 4 5 6 User user = new User("VK" ,23 ,"Test@gmail.com" ); Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DOTS) .create(); System.out.println(gson.toJson(user));
GsonBuilder.setFieldNamingStrategy 方法需要与Gson提供的FieldNamingStrategy接口配合使用,用于将POJO字段与JSON字段对应,FieldNamingPolicy也可以使用setFieldNamingStrategy方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 User user = new User("VK" ,23 ,"Test@gmail.com" ); Gson gson = new GsonBuilder() .setFieldNamingStrategy(new FieldNamingStrategy() { @Override public String translateName (Field field) { if ("emailAddress" .equals(field.getName())) { return "email" ; } return field.getName(); } }) .create(); System.out.println(gson.toJson(user));
7.TypeAdapter
1.TypeAdapter是Gson自2.0开始提供的一个抽象类,用于接管某种类型的序列化和反序列化过程,包含两个注要方法write(JsonWriter,T)
和read(JsonReader)
其它方法都是final方法并最终调用这两个抽象方法。
2.TypeAdapter 以及 JsonSerializer 和 JsonDeserializer 都需要与GsonBuilder.registerTypeAdapter
或GsonBuilder.registerTypeHierarchyAdapter
配合使用。
jsonWrite方法
jsonWriter写入字符
beginArray
[
endArray
]
beginObject
{
endObject
}
1 2 3 4 5 public class User { private String name; private Integer age; private String email; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 public abstract class TypeAdapter <T > { public TypeAdapter () { } public abstract void write (JsonWriter var1, T var2) throws IOException ; public final void toJson (Writer out, T value) throws IOException { JsonWriter writer = new JsonWriter(out); this .write(writer, value); } public final TypeAdapter<T> nullSafe () { return new TypeAdapter<T>() { public void write (JsonWriter out, T value) throws IOException { if (value == null ) { out.nullValue(); } else { TypeAdapter.this .write(out, value); } } public T read (JsonReader reader) throws IOException { if (reader.peek() == JsonToken.NULL) { reader.nextNull(); return null ; } else { return TypeAdapter.this .read(reader); } } }; } public final String toJson (T value) { StringWriter stringWriter = new StringWriter(); try { this .toJson(stringWriter, value); } catch (IOException var4) { throw new AssertionError(var4); } return stringWriter.toString(); } public final JsonElement toJsonTree (T value) { try { JsonTreeWriter jsonWriter = new JsonTreeWriter(); this .write(jsonWriter, value); return jsonWriter.get(); } catch (IOException var3) { throw new JsonIOException(var3); } } public abstract T read (JsonReader var1) throws IOException ; public final T fromJson (Reader in) throws IOException { JsonReader reader = new JsonReader(in); return this .read(reader); } public final T fromJson (String json) throws IOException { return this .fromJson((Reader)(new StringReader(json))); } public final T fromJsonTree (JsonElement jsonTree) { try { JsonReader jsonReader = new JsonTreeReader(jsonTree); return this .read(jsonReader); } catch (IOException var3) { throw new JsonIOException(var3); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class UserTypeAdapter extends TypeAdapter <User > { @Override public void write (JsonWriter jsonWriter, User user) throws IOException { jsonWriter.beginObject(); jsonWriter.name("name" ).value(user.getName()); jsonWriter.name("age" ).value(user.getAge()); jsonWriter.name("emailAddress" ).value(user.getEmail()); jsonWriter.endObject(); } @Override public User read (JsonReader jsonReader) throws IOException { User user = new User(); jsonReader.beginObject(); while (jsonReader.hasNext()) { switch (jsonReader.nextName()) { case "name" : user.setName(jsonReader.nextString()); break ; case "age" : user.setAge(jsonReader.nextInt()); break ; case "emailAddress" : user.setEmail(jsonReader.nextString()); break ; } } jsonReader.endObject(); return user; } }
1 2 3 4 5 6 7 8 User user = new User("Gori" , 72 ,"Gori101@gamil.com" ); Gson gson = new GsonBuilder() .registerTypeAdapter(User.class, new UserTypeAdapter()) .create(); System.out.println(gson.toJson(user)); String str = "{\"name\":\"vita\",\"age\":43,\"emailAddress\":\"VitaOne@gamil.com\"}" ; System.out.println(gson.fromJson(str,User.class));
8.JsonSerializer与JsonDeserializer
Gson 使用 JsonSerializer 接管序列化过程,JsonDeserializer 接管反序列化过程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Gson gson = new GsonBuilder() .registerTypeAdapter(Integer.class, new JsonDeserializer<Integer>() { @Override public Integer deserialize (JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { try { int value = jsonElement.getAsInt(); if (value>=24 ){ return value%24 ; } return value; }catch (NumberFormatException e) { return -1 ; } } }) .create(); System.out.println(gson.fromJson("10" ,Integer.class)); System.out.println(gson.fromJson("1023" ,Integer.class)); System.out.println(gson.fromJson("err" ,Integer.class)); System.out.println(gson.fromJson("\"\"" ,Integer.class));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 JsonSerializer<Number> numberJsonSerializer = new JsonSerializer<Number>() { @Override public JsonElement serialize (Number src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(String.valueOf(src)); } }; JsonSerializer<String> stringJsonSerializer = new JsonSerializer<String>() { @Override public JsonElement serialize (String arg0, Type arg1, JsonSerializationContext arg2) { return new JsonPrimitive(arg0 + "_ADD" ); } }; Gson strGson = new GsonBuilder() .registerTypeAdapter(String.class, stringJsonSerializer) .create(); System.out.println(strGson.toJson("JSON" )); Gson numberGson = new GsonBuilder() .registerTypeAdapter(Integer.class, numberJsonSerializer) .registerTypeAdapter(Long.class, numberJsonSerializer) .registerTypeAdapter(Float.class, numberJsonSerializer) .registerTypeAdapter(Double.class, numberJsonSerializer) .create(); System.out.println(numberGson.toJson(100.0f )); Gson numberGsonWitheHierarchy = new GsonBuilder() .registerTypeHierarchyAdapter(Number.class, numberJsonSerializer) .create(); System.out.println(numberGsonWitheHierarchy.toJson(100.01 ));
1.registerTypeAdapter支持泛型,registerTypeHierarchyAdapter支持继承。
2.如果一个被序列化的对象本身带有泛型且注册相应的TypeAdapter,那么必须调用Gson.toJson(Object,Type)
,明确告诉Gson对象类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 Type type= new TypeToken<List<User>>(){}.getType(); TypeAdapter typeAdapter = new TypeAdapter<List<User>>() { @Override public void write (JsonWriter jsonWriter, List<User> users) throws IOException { jsonWriter.beginArray(); for (User user:users){ jsonWriter.beginObject(); jsonWriter.name("name" ).value(user.getName()); jsonWriter.name("age" ).value(user.getAge()); jsonWriter.name("emailAddress" ).value(user.getEmail()); jsonWriter.endObject(); } jsonWriter.endArray(); } @Override public List<User> read (JsonReader jsonReader) throws IOException { return null ; } }; Gson gson = new GsonBuilder() .registerTypeAdapter(type, typeAdapter) .create(); List<User> list = new ArrayList<>(); list.add(new User("T1" ,11 ,"t1User@qq.com" )); list.add(new User("T2" ,22 ,"t2User@qq.com" )); String result = gson.toJson(list, type); System.out.println(result);
9.TypeAdapterFactory
可用于创建TypeAdapter的工厂类,通过对比Type,确定有无对应的TypeAdapter,没有返回null。
1 2 3 4 5 6 7 8 9 10 11 Gson gson = new GsonBuilder() .registerTypeAdapterFactory(new TypeAdapterFactory() { @Override public <T> TypeAdapter<T> create (Gson gson, TypeToken<T> typeToken) { if (typeToken.getType().equals(type)){ return typeAdapter; } return null ; } }) .create();
CollectionTypeAdapterFactory中的create方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 public <T> TypeAdapter<T> create (Gson gson, TypeToken<T> typeToken) { Type type = typeToken.getType(); Class<? super T> rawType = typeToken.getRawType(); if (!Collection.class.isAssignableFrom(rawType)) { return null ; } else { Type elementType = Types.getCollectionElementType(type, rawType); TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); ObjectConstructor<T> constructor = this .constructorConstructor.get(typeToken); TypeAdapter<T> result = new CollectionTypeAdapterFactory.Adapter(gson, elementType, elementTypeAdapter, constructor); return result; } }
10.JsonAdapter
1.JsonAdapter注解位于POJO类上,接收一个参数且必须是
TypeAdpater
TypeAdapterFactory
JsonSerializer
JsonDeserializer
且JsonAdapter无需使用GsonBuilder进行注册。
2.JsonAdapter的优先级比GsonBuilder.registerTypeAdapter
的优先级更高。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 public class UserTypeAdapter extends TypeAdapter <User > { @Override public void write (JsonWriter jsonWriter, User user) throws IOException { jsonWriter.beginObject(); jsonWriter.name("name" ).value(user.getName()); jsonWriter.name("age" ).value(user.getAge()); jsonWriter.name("email_Address" ).value(user.getEmail()); jsonWriter.endObject(); } @Override public User read (JsonReader jsonReader) throws IOException { User user = new User(); jsonReader.beginObject(); while (jsonReader.hasNext()) { switch (jsonReader.nextName()) { case "name" : user.setName(jsonReader.nextString()); break ; case "age" : user.setAge(jsonReader.nextInt()); break ; case "emailAddress" : user.setEmail(jsonReader.nextString()); break ; } } jsonReader.endObject(); return user; } }
1 2 3 4 Gson gson = new Gson(); User user = new User("SOM" , 74 , "SONM@qq.com" ); System.out.println(gson.toJson(user));
Pojo Bean What is java pojo class, java bean, normal class?
1.Java Beans
:
All properties private (use getters/setters)
A public no-argument constructor
Implements Serializable.
2.Pojo
: Plain Old Java Object is a Java object not bound by any restriction other than those forced by the Java Language Specification. I.e., a POJO should not have to
Extend prespecified classes
Implement prespecified interface
Contain prespecified annotations
POJO通常是不需要是任何类的子类和实现特定的接口以及遵循特定的模式。