![](/img/trans.png)
[英]Is There A Library That Converts Any String Into A Valid Class Name That Is Compliant To Code Conventions
[英]Is there any tool or library that converts YAML or XML files into Java code?
是否有工具或庫可以將序列化為YAML的對象或XML文件轉換為創建該對象的Java代碼?
從技術角度來看,我認為這里沒有困難。 Yaml和XStream(或其他類似工具)都需要通過反射查找Java類名稱,查找構造函數,調用它,然后查找設置器並調用它們。 反射調用可以被相同的Java代碼生成所代替。 但是,這需要一些工作。
是否存在這樣的工具? 還是有人正在開發它並想與公眾共享?
PS任何能夠將給定Java對象轉換為Java代碼的庫都可以滿足我的需求。
澄清
我希望該工具能夠轉換示例YAML:
--- !pl.example.Contact
name: Nathan Sweet
age: 28
或XML:
<contact>
<name>Nathan Sweet</name>
<age>28</age>
</contact>
進入代碼:
pl.example.Contact contact = new pl.example.Contact();
contact.setName("Nathan Sweet");
contact.setAge(28);
我曾經問過有關將YAML或XML轉換為Java代碼的問題,但是我真正需要的是生成將創建給定Java對象的Java代碼。 可以通過許多Java YAML庫之一來讀取現有的YAML。
但是,我找不到任何可以從給定Java對象創建Java代碼的庫。 也許我在搜索錯誤的關鍵字,也許我太早完成搜索,但是我什么都沒找到。
我自己編寫了該工具。 該代碼非常原始,在很多情況下可能還不夠(它不支持抽象類和接口等),但是對於我要完成的任務來說已經足夠了。 因此,我將解決方案的源代碼發布為我的問題的答案:
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringEscapeUtils;
public class BeanCodeGenerator {
private class Context {
private int index;
private StringBuilder sb = new StringBuilder();
private String br = "\n\t\t";
}
public String generateBeanMethod(Object bean, String methodName) {
Context ctx = new Context();
Class type = _getBeanClass(bean);
ctx.sb.append("\tpublic ").append(type.getCanonicalName()).append(" ").append(methodName)
.append("() {").append(ctx.br);
String vname = "null";
try {
vname = _valueStr(bean, type, ctx);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
ctx.sb.append("return ").append(vname).append(";\n");
ctx.sb.append("\t}\n");
return ctx.sb.toString();
}
private String _outputBean(Object bean, Context ctx) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// output block of code creating bean
String vname = "v" + ctx.index;
String cname = bean.getClass().getCanonicalName();
ctx.sb.append(cname).append(" ").append(vname).append(" = new ").append(cname).append("();").append(ctx.br);
PropertyDescriptor[] props = PropertyUtils.getPropertyDescriptors(bean);
for (PropertyDescriptor prop : props) {
if (prop.getReadMethod() == null || prop.getWriteMethod() == null)
continue; // skip such 'properties'
Object value = prop.getReadMethod().invoke(bean);
if (value == null)
continue;
String valueStr = _valueStr(value, prop.getReadMethod().getReturnType(), ctx);
if (valueStr != null) {
ctx.sb.append(vname).append(".").append(prop.getWriteMethod().getName()).append("(")
.append(valueStr).append(");").append(ctx.br);
}
}
return vname;
}
private Class _getBeanClass(Object bean) {
if (bean == null)
return null;
if (_isCollection(bean)) {
if (bean instanceof List)
return ArrayList.class;
if (bean instanceof Set)
return HashSet.class;
if (bean instanceof Map)
return HashMap.class;
}
return bean.getClass();
}
private String _valueStr(Object value, Class type, Context ctx) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String valueStr = _outputValue(value, type);
if (valueStr == null) {
if (_isBean(value)) {
ctx.index++;
valueStr = _outputBean(value, ctx);
} else if (_isCollection(value)) {
ctx.index++;
valueStr = _outputCollection(value, ctx);
}
}
if (valueStr == null)
valueStr = "null";
return valueStr;
}
private String _outputCollection(Object collection, Context ctx) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
String vname = "v" + ctx.index;
if (collection instanceof List) {
ctx.sb.append("java.util.ArrayList ").append(vname).append(" = new java.util.ArrayList();").append(ctx.br);
List list = (List) collection;
for (Object value : list) {
if (value == null) {
ctx.sb.append(vname).append(".add(null);").append(ctx.br);
continue;
}
String valueStr = _valueStr(value, value.getClass(), ctx);;
ctx.sb.append(vname).append(".add(").append(valueStr).append(");").append(ctx.br);
}
} else if (collection instanceof Set) {
ctx.sb.append("java.util.HashSet ").append(vname).append(" = new java.util.HashSet();").append(ctx.br);
Set set = (Set) collection;
for (Object value : set) {
if (value == null) {
ctx.sb.append(vname).append(".add(null);").append(ctx.br);
continue;
}
String valueStr = _valueStr(value, value.getClass(), ctx);;
ctx.sb.append(vname).append(".add(").append(valueStr).append(");").append(ctx.br);
}
} else if (collection instanceof Map) {
ctx.sb.append("java.util.HashMap ").append(vname).append(" = new java.util.HashMap();").append(ctx.br);
Map map = (Map) collection;
for (Object item : map.entrySet()) {
Map.Entry entry = (Map.Entry) item;
String valueStr = "null";
String keyStr = "null";
if (entry.getKey() != null) {
keyStr = _valueStr(entry.getKey(), entry.getKey().getClass(), ctx);
}
if (entry.getValue() != null) {
valueStr = _valueStr(entry.getValue(), entry.getValue().getClass(), ctx);
}
ctx.sb.append(vname).append(".put(").append(keyStr).append(", ").append(valueStr).append(");").append(ctx.br);
}
}
return vname;
}
private boolean _isBean(Object value) throws SecurityException {
if (value == null)
return false;
if (_isCollection(value))
return false;
Class type = value.getClass();
try {
type.getConstructor();
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
private boolean _isCollection(Object value) {
if (value == null)
return false;
Class type = value.getClass();
return List.class.isAssignableFrom(type) || Set.class.isAssignableFrom(type) || Map.class.isAssignableFrom(type);
}
// output simple value, returns null for non-singleliners
private String _outputValue(Object value, Class type) {
if (value == null)
return null;
Class vtype = value.getClass();
if (type == long.class) {
return value.toString() + "L";
}
if (type == float.class) {
return value.toString() + "F";
}
if (type == short.class) {
return "(short) " + value.toString() + "";
}
if (type.isPrimitive()) {
return value.toString();
}
if (String.class.isAssignableFrom(type)) {
return '"' + StringEscapeUtils.escapeJava(value.toString()) + '"';
}
if (Integer.class == type || Double.class == type || Boolean.class == type) {
return type.getName() + ".valueOf(" + value.toString() + ")";
}
if (Long.class == type) {
return type.getName() + ".valueOf(" + value.toString() + "L)";
}
if (Short.class == type) {
return type.getName() + ".valueOf((short)" + value.toString() + ")";
}
if (Float.class == type) {
return type.getName() + ".valueOf(" + value.toString() + "F)";
}
if (Date.class.isAssignableFrom(type)) {
Date date = (Date) value;
return "new java.util.Date(" + date.getTime() + "L)";
}
return null;
}
}
您可以在此處檢查YamlBeans庫。
它可以讀寫Yaml格式的bean。
這是他們的文檔示例:
name: Nathan Sweet
age: 28
public class Contact {
public String name;
public int age;
}
YamlReader reader = new YamlReader(new FileReader("contact.yml"));
Contact contact = reader.read(Contact.class);
System.out.println(contact.age);
此外,似乎Yaml對JAXB的支持
編輯:
根據您的澄清,不,我不知道有任何一個lib可以立即執行此操作,但是要做起來並不難(取決於您要加載的對象的復雜程度)。
是的,您可以使用swagger集線器,它可以為您提供來自YAML的客戶端和服務器的代碼(多種語言)。 我也使用相同的工具,它具有為REST API甚至生成代碼的功能。
網址: http : //editor.swagger.io/
教程網址: https : //swagger.io/tools/open-source/getting-started/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.