私は少し前に解決策にたどり着きましたが、それを投稿する時間とエネルギーがありませんでしたが、ここに行きます:
注: このソリューションは、誰もが夢見る完璧な 2 行のソリューションではありませんが、私が望んでいたとおりに機能します。注意 2: このソリューションでは、XML ファイルを読み取るためにXOMライブラリが必要です。
まず、どのように機能するか: 一連の XML ファイルを作成します。各ファイルは、jackson によってシリアル化される (またはカスタマイズされたシリアル化が必要な) 1 つのエンティティを表します。
以下はそのようなファイルの例です - Assignment.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<Assignment>
<endDate/>
<id/>
<missionType>
<id/>
<name/>
</missionType>
<numberOfDaysPerWeek/>
<project>
<id/>
<name/>
</project>
<resource>
<id/>
<firstName/>
<lastName/>
<fte/>
</resource>
<role>
<id/>
<name/>
</role>
<startDate/>
<workLocation/>
</Assignment>
ここでは、XML 要素として表された各属性で表された Assignment クラスがあります。表されていない要素は、後で示すコンバーターを使用してシリアル化されないことに注意してください。
子要素を持つ要素は、Assignment インスタンスによって参照されるオブジェクトです。これらの子要素は、残りの要素と一緒にシリアル化されます。
たとえば、Assignment インスタンスには、"role" という名前の属性があり、そのタイプは であり、シリアル化Role
する必要role
があります。id
name
これは主に、シリアル化するものとシリアル化しないものを選択して、シリアル化の深さを制限する方法です。
今ObjectConverter
クラスに:
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import nu.xom.Builder;
import nu.xom.Document;
import nu.xom.Element;
import nu.xom.Elements;
import nu.xom.ParsingException;
import nu.xom.ValidityException;
import model.ModelObject;
/**
* This helper class will convert DOM objects (those implementing ModelObject) into a data structure built on the fly.
* Typically, a simple object will be converted into a Map<String, Object> where keys will be the object's field names and values be corresponding field values.
* The convertion uses an XML configuration file that is located in webservices/jackson/converters.
*
* @author mdekeys
*
*/
public class ObjectConverter {
private static Logger logger = Logger.getLogger(ObjectConverter.class);
private static final String CONFIGURATION_DIR = "../standalone/deployments/resources-management.war/WEB-INF/classes/com/steria/rm/webservices/jackson/converters/";
/**
*
* @param obj The object to convert
* @param element An XML element (based on XOM library) which represents the object structure.
* @return Returns the object converted in a corresponding data structure
*/
@SuppressWarnings("unchecked")
private static Object serialize(ModelObject obj, Element element) {
//initialize return value
Map<String, Object> map = new HashMap<String, Object>();
//find all child elements
Elements children = element.getChildElements();
//loop through children elements
for (int i = 0; i < children.size(); i++) {
//get the current child
Element child = children.get(i);
//child's qualifiedName shoud be the name of an attribute
String fieldName = child.getQualifiedName();
//find get method for this attribute
Method getMethod = null;
try {
getMethod = obj.getConvertedClass().getMethod("get" + firstLetterToUpperCase(fieldName));
} catch (NoSuchMethodException e) {
logger.error("Cannot find getter for "+fieldName, e);
return null;
} catch (SecurityException e) {
logger.error("Cannot access getter for "+fieldName, e);
return null;
}
//invoke get method
Object value = null;
try {
value = getMethod.invoke(obj, (Object[]) null);
} catch (IllegalAccessException e) {
logger.error("Cannot invoke getter for "+fieldName, e);
return null;
} catch (IllegalArgumentException e) {
logger.error("Bad arguments passed to getter for "+fieldName, e);
return null;
} catch (InvocationTargetException e) {
logger.error("Cannot invoke getter for "+fieldName, e);
return null;
}
//if value is null, return null
if (value == null || (value instanceof List && ((List<?>) value).size() == 0)) {
map.put(fieldName, null);
} else if (value instanceof List<?>) { //if value is a list, recursive call
map.put(fieldName, serializeList((List<ModelObject>) value, child));
} else if (value instanceof ModelObject) { //if value is another convertable object, recursive call
map.put(fieldName, serialize((ModelObject) value, child));
} else { //simple value, put it in
map.put(fieldName, value);
}
}
return map;
}
/**
* Intermediary method that is called from outside of this class.
* @param list List of objects to be converted.
* @param confFileName Name of the configuration file to be used.
* @return The list of converted objects
*/
public static List<Object> serializeList(List<ModelObject> list, String confFileName) {
return serializeList(list, findRootElement(confFileName));
}
/**
* Method that is called inside this class with an XML element (based on XOM library)
* @param list List of objects to be converted.
* @param element XML element (XOM) representing the object's structure
* @return List of converted objects.
*/
public static List<Object> serializeList(List<ModelObject> list, Element element) {
ArrayList<Object> res = new ArrayList<Object>();
for (ModelObject obj : list) {
res.add(serialize(obj, element));
}
return res;
}
/**
* Method that is called from outside of this class.
* @param object Object to be converted.
* @param confFileName Name of the XML file to use for the convertion.
* @return Converted object.
*/
public static Object serialize(ModelObject object, String confFileName) {
return serialize(object, findRootElement(confFileName));
}
/**
* Helper method that is used to set the first letter of a String to upper case.
* @param str The string to be modified.
* @return Returns the new String with its first letter in upper case.
*/
private static String firstLetterToUpperCase(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
/**
* Helper method that is taking an XML configuration file name and returns its the root element (based on XOM library).
* @param confFileName Name of the XML configuration file
* @return Returns the root element (XOM based)
*/
private static Element findRootElement(String confFileName) {
Builder parser = new Builder();
Document doc = null;
String confFile = confFileName + ".xml";
try {
doc = parser.build(CONFIGURATION_DIR + confFile);
} catch (ValidityException e) {
doc = e.getDocument();
logger.warn("XML configuration file for "+confFileName+" isn't valid", e);
} catch (ParsingException e) {
logger.error("XML configuration file for "+confFileName+" isn't parseable", e);
} catch (IOException e) {
logger.error("IOException on XML configuration file for "+confFileName, e);
}
return doc.getRootElement();
}
}
ご覧のとおり、serialize、serializeList、および serializeMap メソッドModelObject
には、すべてのシリアライズ可能なオブジェクトが実装する必要があるインターフェイスである引数が必要です (以下で提供)。
すべてのドメイン オブジェクトを 1 つの特定のタイプにまとめて再グループ化するために使用されるインターフェイスが既にある場合は、このインターフェイスも使用できます (メソッドを 1 つ追加するだけで済みます。以下を参照してください)。
インターフェース ModelObject :
/**
* Interface that identifies an object as a DOM object and is used by class {@ObjectConverter} to retrieve the class of the object to convert.
* @author mdekeys
*
*/
public interface ModelObject {
/**
* This method returns the implementer's class
* @return The implementer Class
*/
Class<?> getConvertedClass();
}
この ObjectConverter を次のように使用します。
@Override
@RequestMapping(value = "/populatedLists", method = RequestMethod.GET)
public @ResponseBody Map<String, Object> populateLists() {
Map<String, Object> map = new HashMap<String, Object>();
final List<ModelObject> assignments = (List<ModelObject>)(List<?>) this.assignmentService.listAll();
final List<ModelObject> projects = (List<ModelObject>)(List<?>) this.projectService.listAll();
map.put("assignments", ObjectConverter.serializeList(assignments, "Assignment"));
map.put("projects", ObjectConverter.serializeList(projects, "Project"));
return map;
}
PS: 奇妙なキャストは無視してください。これは、XX を YY にキャストできることがわかっている場合に、XX のリストを YY のリストに変換するための Java のトリックです。
ご覧のとおり、これは Jackson に加えて使用されます。DB からオブジェクトのリストまたは単一のオブジェクトを取得し、ObjectConverter の特殊なメソッド (serializeList など) を使用してそれらを変換し、XML 構成にキーを提供します。ファイル (例: Assignment.xml)。次に、Jackson 自身によってシリアル化された Map にそれらを追加します。
したがって、XML ファイルを読み取るこの ObjectConverter の目的は、これらの XML ファイルを使用してカスタマイズできるデータ構造を構築することです。これにより、シリアル化する必要があるオブジェクトごとにコンバーター クラスを作成する必要がなくなります。
ObjectConverter クラスは、XML ファイルのすべての要素をループしてから、java.lang.reflect パッケージを使用して、変換するオブジェクト内のこれらの属性を見つけます。
XML ファイルではスペルが非常に重要であることは明らかですが、順序は重要ではありません。
私はそのソリューションを自分で使用し、独自の小さなアプリを使用して、すべての XML ファイルを生成し、必要に応じてカスタマイズすることができました。これは重いように思えるかもしれませんが、これは本当に私を大いに助け、パフォーマンスの低下は見られませんでした.
これが役立つことを願っています!