策略html |
描述java |
Sourcegit |
編譯器會丟棄註解github |
Classspring |
註解是在編譯器生成的類文件中記錄的,但不須要在運行時處理類文件的Java虛擬機(JVM)保留。編程 |
Runtimejson |
註解由編譯器記錄在類文件中,並由JVM在運行時保留api |
目標數組 |
描述bash |
Annotation Type |
註解另外一個註解 |
Constructor |
註解構造函數 |
Field |
註解一個字段,例如類的實例變量或枚舉常量 |
Local variable |
註解局部變量 |
Method |
註解類的方法 |
Module |
註解模塊(Java 9中的新增功能) |
Package |
註解包 |
Parameter |
註解到方法或構造函數的參數 |
Type |
註解一個類型,例如類,接口,註解類型或枚舉聲明 |
Type Parameter |
註解類型參數,例如用做通用參數形式的參數 |
Type Use |
註解類型的使用,例如當使用new關鍵字建立類型的對象時 ,當對象強制轉換爲指定類型時,類實現接口時,或者使用throws關鍵字聲明throwable對象的類型時(有關更多信息,請參閱Type Annotations and Pluggable Type Systems Oracle tutorial) |
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface JsonField {
public String value() default "";
}複製代碼
咱們聲明的核心是public @interface JsonField,聲明帶有public修飾符的註解——容許咱們的註解在任何包中使用(假設在另外一個模塊中正確導入包)。註解聲明一個String類型value的參數,默認值爲空字符串。
public class Car {
@JsonField("manufacturer")
private final String make;
@JsonField
private final String model;
private final String year;
public Car(String make, String model, String year) {
this.make = make;
this.model = model;
this.year = year;
}
public String getMake() {
return make;
}
public String getModel() {
return model;
}
public String getYear() {
return year;
}
@Override
public String toString() {
return year + " " + make + " " + model;
}
} 複製代碼
該類使用@JsonField註解的兩個主要用途:(1)具備顯式值,(2)具備默認值。咱們也可使用@JsonField(value = "someName")註解一個字段,但這種樣式過於冗長,並無助於代碼的可讀性。所以,除非在單元素註解中包含註解參數名稱能夠增長代碼的可讀性,不然應該省略它。對於具備多個參數的註解,須要顯式指定每一個參數的名稱來區分參數(除非僅提供一個參數,在這種狀況下,若是未顯式提供名稱,則參數將映射到value參數)。
public class JsonSerializer {
public String serialize(Object object) throws JsonSerializeException {
try {
Class<?> objectClass = requireNonNull(object).getClass();
Map<String, String> jsonElements = new HashMap<>();
for (Field field : objectClass.getDeclaredFields()) {
field.setAccessible(true);
if (field.isAnnotationPresent(JsonField.class)) {
jsonElements.put(getSerializedKey(field), (String) field.get(object));
}
}
System.out.println(toJsonString(jsonElements));
return toJsonString(jsonElements);
} catch (IllegalAccessException e) {
throw new JsonSerializeException(e.getMessage());
}
}
private String toJsonString(Map<String, String> jsonMap) {
String elementsString = jsonMap.entrySet().stream().map(entry -> "\"" + entry.getKey() + "\":\"" + entry.getValue() + "\"").collect(Collectors.joining(","));
return "{" + elementsString + "}";
}
private static String getSerializedKey(Field field) {
String annotationValue = field.getAnnotation(JsonField.class).value();
if (annotationValue.isEmpty()) {
return field.getName();
} else {
return annotationValue;
}
}
} 複製代碼
請注意,爲簡潔起見,已將多個功能合併到該類中。有關此序列化程序類的重構版本,請參閱codebase存儲庫中的此分支(https://github.com/albanoj2/dzone-json-serializer/tree/srp_generalization)。咱們還建立了一個異常,用於表示在serialize方法處理對象時是否發生了錯誤:
public class JsonSerializeException extends Exception {
private static final long serialVersionUID = -8845242379503538623L;
public JsonSerializeException(String message) {
super(message);
}
} 複製代碼
儘管JsonSerializer該類看起來很複雜,但它包含三個主要任務:(1)查找使用@JsonField註解的全部字段,(2)記錄包含@JsonField註解的全部字段的名稱(或顯式提供的字段名稱)和值,以及(3)將所記錄的字段名稱和值的鍵值對轉換成JSON字符串。
Car car=new Car("Ford","F150","2018");
JsonSerializer serializer=new JsonSerializer();
serializer.serialize(car); 複製代碼
輸出:
{"model":"F150","manufacturer":"Ford"}複製代碼