web-dev-qa-db-ja.com

速度テンプレートに似たJavaの文字列置換

JavaにString置換メカニズムはありますか。テキストでオブジェクトを渡すことができ、発生時に文字列を置換します。
たとえば、テキストは次のとおりです。

Hello ${user.name},
    Welcome to ${site.name}. 

私が持っているオブジェクトは"user""site"です。 ${}内で指定された文字列を、オブジェクトからの同等の値に置き換えたいと思います。これは、速度テンプレート内のオブジェクトを置き換えるのと同じです。

77
Joe

Java.text.MessageFormat クラス、MessageFormatはオブジェクトのセットを受け取り、それらをフォーマットし、フォーマットされた文字列を適切な場所のパターンに挿入します。

Object[] params = new Object[]{"hello", "!"};
String msg = MessageFormat.format("{0} world {1}", params);
115
RealHowTo

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);
119
JH.

これの小さなテスト実装をまとめました。基本的な考え方は、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が何であるかわからないことにも言及する必要があるため、この回答が関連することを願っています。

18
jjnguy

私の好ましい方法は、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 を使用するため、好きなだけ変数を入れることができます

12
artgrohe

これを行う方法の概要を次に示します。実際のコードとして実装するのは比較的簡単です。

  1. テンプレートで参照されるすべてのオブジェクトのマップを作成します。
  2. 正規表現を使用して、テンプレート内の変数参照を見つけ、それらを値に置き換えます(手順3を参照)。 Matcher クラスは、検索と置換に便利です。
  3. 変数名をドットで分割します。 user.nameuserおよびnameになります。マップ内でuserを検索してオブジェクトを取得し、 reflection を使用してオブジェクトからnameの値を取得します。オブジェクトに標準のゲッターがある場合、getNameメソッドを探して呼び出します。
5
casablanca

あなたのためにこれを行うExpression Languageの実装がいくつかあります。要件が増えた場合、または必要に応じて独自の実装を使用することをお勧めします。たとえば、 [〜#〜] juel [〜#〜] および [〜#〜] mvel [〜#〜]

MVELが好きで、少なくとも1つのプロジェクトで正常に使用できました。

Stackflowの投稿も参照してください 非JSP(スタンドアロン)コンテキストでのJSTL/JSP EL(式言語)

4

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);
0
Kan

速度はまさにその問題を解決するために書かれているため、速度に匹敵するものは何もありません。あなたが試すことができる最も近いものはフォーマッタを調べることです

http://cupi2.uniandes.edu.co/site/images/recursos/javadoc/j2se/1.5.0/docs/api/Java/util/Formatter.html

ただし、私が知っている限り、フォーマッタはJavaのようにCのようなフォーマットオプションを提供するために作成されました。

0
Mike Milkin