JavaにString
置換メカニズムはありますか。テキストでオブジェクトを渡すことができ、発生時に文字列を置換します。
たとえば、テキストは次のとおりです。
Hello ${user.name},
Welcome to ${site.name}.
私が持っているオブジェクトは"user"
と"site"
です。 ${}
内で指定された文字列を、オブジェクトからの同等の値に置き換えたいと思います。これは、速度テンプレート内のオブジェクトを置き換えるのと同じです。
Java.text.MessageFormat
クラス、MessageFormatはオブジェクトのセットを受け取り、それらをフォーマットし、フォーマットされた文字列を適切な場所のパターンに挿入します。
Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);
Apache Commons LangのStrSubstitutor
を使用します。
https://commons.Apache.org/proper/commons-lang/
それはあなたのためにそれをします(そしてそのオープンソース...)
Map<String, String> valuesMap = new HashMap<String, String>();
valuesMap.put("animal", "quick brown fox");
valuesMap.put("target", "lazy dog");
String templateString = "The ${animal} jumped over the ${target}.";
StrSubstitutor sub = new StrSubstitutor(valuesMap);
String resolvedString = sub.replace(templateString);
これの小さなテスト実装をまとめました。基本的な考え方は、format
を呼び出し、フォーマット文字列、オブジェクトのマップ、およびそれらがローカルに持っている名前を渡すことです。
次の出力は次のとおりです。
私の犬はfidoという名前で、ジェーンドゥーが彼を所有しています。
public class StringFormatter {
private static final String fieldStart = "\\$\\{";
private static final String fieldEnd = "\\}";
private static final String regex = fieldStart + "([^}]+)" + fieldEnd;
private static final Pattern pattern = Pattern.compile(regex);
public static String format(String format, Map<String, Object> objects) {
Matcher m = pattern.matcher(format);
String result = format;
while (m.find()) {
String[] found = m.group(1).split("\\.");
Object o = objects.get(found[0]);
Field f = o.getClass().getField(found[1]);
String newVal = f.get(o).toString();
result = result.replaceFirst(regex, newVal);
}
return result;
}
static class Dog {
public String name;
public String owner;
public String gender;
}
public static void main(String[] args) {
Dog d = new Dog();
d.name = "fido";
d.owner = "Jane Doe";
d.gender = "him";
Map<String, Object> map = new HashMap<String, Object>();
map.put("d", d);
System.out.println(
StringFormatter.format(
"My dog is named ${d.name}, and ${d.owner} owns ${d.gender}.",
map));
}
}
注:未処理の例外のため、これはコンパイルされません。しかし、コードを読みやすくします。
また、コードで自分でマップを作成する必要があるのは好きではありませんが、ローカル変数の名前をプログラムで取得する方法がわかりません。最適な方法は、オブジェクトを作成したらすぐにマップに配置することを忘れないことです。
次の例は、例から必要な結果を生成します。
public static void main(String[] args) {
Map<String, Object> map = new HashMap<String, Object>();
Site site = new Site();
map.put("site", site);
site.name = "StackOverflow.com";
User user = new User();
map.put("user", user);
user.name = "jjnguy";
System.out.println(
format("Hello ${user.name},\n\tWelcome to ${site.name}. ", map));
}
Velocityが何であるかわからないことにも言及する必要があるため、この回答が関連することを願っています。
私の好ましい方法は、String.format()
です。これは、ワンライナーであり、サードパーティのライブラリを必要としないためです。
_String result = String.format("Hello! My name is %s, I'm %s.", NameVariable, AgeVariable);
_
これは、次のような例外メッセージで非常に頻繁に使用します。
_throw new Exception(String.format("Unable to login with email: %s", email));
_
ヒント:format()
は Varargs を使用するため、好きなだけ変数を入れることができます
これを行う方法の概要を次に示します。実際のコードとして実装するのは比較的簡単です。
user.name
はuser
およびname
になります。マップ内でuser
を検索してオブジェクトを取得し、 reflection を使用してオブジェクトからname
の値を取得します。オブジェクトに標準のゲッターがある場合、getName
メソッドを探して呼び出します。あなたのためにこれを行うExpression Languageの実装がいくつかあります。要件が増えた場合、または必要に応じて独自の実装を使用することをお勧めします。たとえば、 [〜#〜] juel [〜#〜] および [〜#〜] mvel [〜#〜]
MVELが好きで、少なくとも1つのプロジェクトで正常に使用できました。
Stackflowの投稿も参照してください 非JSP(スタンドアロン)コンテキストでのJSTL/JSP EL(式言語)
JavaでGroovyShellを使用して、Groovy GStringでテンプレートを解析します。
Binding binding = new Binding();
GroovyShell gs = new GroovyShell(binding);
// this JSONObject can also be replaced by any Java Object
JSONObject obj = new JSONObject();
obj.put("key", "value");
binding.setProperty("obj", obj)
String str = "${obj.key}";
String exp = String.format("\"%s\".toString()", str);
String res = (String) gs.evaluate(exp);
// value
System.out.println(str);
速度はまさにその問題を解決するために書かれているため、速度に匹敵するものは何もありません。あなたが試すことができる最も近いものはフォーマッタを調べることです
ただし、私が知っている限り、フォーマッタはJavaのようにCのようなフォーマットオプションを提供するために作成されました。