JSON関係の仕様書を作成するため、クラス定義からJSONの文字列を出力するプログラムを作成した。
Mapには未対応のため、ご注意ください。
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.stream.IntStream;
public class PrintJson {
/** インデント用文字 */
private static final String INDENT = " ";
/** JSONに出力する型で定義 */
static XXXXX dto;
public static void main(String[] args) {
try {
System.out.println(getJson(PrintJson.class.getDeclaredField("dto"), 1, null));
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
}
/**
* @param inputField
* JSON出力用のField(ジェネリック対応のため、Classではなく、Field)
* @param level
* インデント用のレベル
* @param parentField
* Fieldの親Field(ジェネリックの型判定用)
* @return Fieldに該当するJSON
*/
private static String getJson(Field inputField, int level, Field parentField) {
StringBuilder sb = new StringBuilder();
Class<?> inputFieldType = inputField.getType();
Class<?> clazz = inputFieldType;
if (inputFieldType.isArray() || isIterable(inputFieldType)) {
sb.append("[");
if (inputFieldType.isArray()) {
clazz = inputFieldType.getComponentType();
} else {
Type type = inputField.getGenericType();
if (type instanceof ParameterizedType) {
Type actualType = ((ParameterizedType) type).getActualTypeArguments()[0];
if (actualType instanceof Class) {
clazz = (Class<?>) actualType;
} else {
clazz = (Class<?>) ((ParameterizedType) parentField.getGenericType())
.getActualTypeArguments()[0];
}
}
}
}
if (clazz.isPrimitive() || (Integer.class == clazz) || (Double.class == clazz) || (Date.class == clazz)
|| (Timestamp.class == clazz) || (Long.class == clazz) || (BigDecimal.class == clazz)
|| (String.class == clazz)) {
sb.append("\"\"");
} else {
sb.append("{").append("\n");
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
sb.append(getIndent(level)).append("\"").append(field.getName()).append("\":");
sb.append(getJson(field, level + 1, inputField)).append(",\n");
}
if (fields.length > 0) {
// 最後の「,」を削除
sb.delete(sb.length() - 2, sb.length() - 1);
}
sb.append(getIndent(level - 1)).append("}");
}
if (inputFieldType.isArray() || isIterable(inputFieldType)) {
sb.append("]");
}
return sb.toString();
}
/**
* @param level
* @return level分のインデント用のスペース
*/
private static String getIndent(int level) {
StringBuilder sb = new StringBuilder();
IntStream.range(0, level).forEach(i -> sb.append(INDENT));
return sb.toString();
}
/**
* @param clazz
* @return clazzがIterableかどうか
*/
private static boolean isIterable(Class<?> clazz) {
if (clazz == Iterable.class) {
return true;
} else {
for (Class<?> clazz1 : clazz.getInterfaces()) {
if (isIterable(clazz1)) {
return true;
}
}
}
return false;
}
}