I'm adding a resource bundle to model like this:
Map<String, Object> root = new HashMap<String, Object>();
Locale locale = org.apache.commons.lang3.LocaleUtils.toLocale(request.getLanguage());
BeansWrapper beansWrapper = new BeansWrapperBuilder(Configuration.VERSION_2_3_21).build();
ResourceBundle bundle = ResourceBundle.getBundle("templates/bundles/messages", locale);
root.put("bundle", new ResourceBundleModel(bundle, beansWrapper));
However, my l10n team doesn't want apostrophes (single quotes character) escaped in my templates like:
bundle.value = You''re account is ready!
Is there anything I can set in my configuration that will output the text as is, avoiding the need to escape the single quotes?
You don't have to (must not actually) escape the apostrophe if you don't have MessageFormat parameters. For example, if this is your .properties file:
m1={0}''s house
m2=Foo''s house
m3=Foo's house
and this is you template:
${bundle.m1}
${bundle.m2}
${bundle.m3}
${bundle('m1', 'Bar')}
then this will be the output:
{0}''s house
Foo''s house
Foo's house
Bar's house
As you can see, the '' was only necessary in the last version.
Related
I am trying to serialize my LinkedHashMap<String,String> to a json file using GSON
what I tried is this:
LinkedHashMap<String, String> resultMap = new LinkedHashMap<>();
resultMap.put("xxxxx","\\u53D1\\u51FA\\u8BE5");
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create;
try (FileWriter fileWriter = new FileWriter("C:\\Users\\xxxxx\\Desktop\\testGson.json")0{
gson.toJson(resultMap, fileWriter);
} catch( IOException e) {
e.printStackTrace();
}
I want the output json value be like \u53D1\u51fa\u8BE5 but for now the output json have double backslashes, basically the unescaped unicode.
How should I do this?
You are storing \\u53D1\\u51FA\\u8BE5 in the map, that is, not the Unicode characters 发 (U+53D1), ... but instead the literal strings \u53D1, \u51FA and \u8BE5. Gson will output these in the JSON string, and escape the \, since otherwise it would change the value of the string (from \u53D1 to 发 and so on).
Unfortunately there is currently no feature to force Gson to use Unicode escapes for non-ASCII characters (in case that is what you wanted), but as shown in this GitHub issue you could provide a custom java.io.Writer which performs the escaping.
I am using Java Properties to read a properties file. Everything is working fine, but Properties silently drops the backslashes.
(i.e.)
original: c:\sdjf\slkdfj.jpg
after: c:sdjfslkdfj.jpg
How do I make Properties not do this?
I am using the code prop.getProperty(key)
I am getting the properties from a file, and I want to avoid adding double backslashes
It is Properties.load() that's causing the problem that you are seeing as backslash is used for a special purpose.
The logical line holding all the data
for a key-element pair may be spread
out across several adjacent natural
lines by escaping the line terminator
sequence with a backslash character,
\.
If you are unable to use CoolBeans's suggestion then what you can do is read the property file beforehand to a string and replace backslash with double-backslash and then feed it to Properties.load()
String propertyFileContents = readPropertyFileContents();
Properties properties = new Properties();
properties.load(new StringReader(propertyFileContents.replace("\\", "\\\\")));
Use double backslashes c:\\sdjf\\slkdfj.jpg
Properties props = new Properties();
props.setProperty("test", "C:\\dev\\sdk\\test.dat");
System.out.println(props.getProperty("test")); // prints C:\dev\sdk\test.dat
UPDATE CREDIT to #ewh below. Apparently, Windows recognises front slashes. So, I guess you can have your users write it with front slashes instead and if you need backslashes afterwards you can do a replace. I tested this snippet below and it works fine.
Properties props = new Properties();
props.setProperty("test", "C:/dev/sdk/test.dat");
System.out.println(props.getProperty("test")); // prints C:/dev/sdk/test.dat
Use forward slashes. There is never a need in Java to use a backslash in a filename.
In case you really need a backslash in a properties file that will be loaded (like for a property that is not a file path) put \u005c for each backslash character.
The backslash is treated specially in properties files as indicated in the document provided by #unhillbilly.
#EJP: Backslash is definitely needed if, for example, you wanted to store an NTLM login id in a properties file, where the format is DOMAIN\USERNAME with a backslash. This type of property is not a filename so forward slashes will not work.
Edit: #Max Nanasy: From the document (java.util.Properties load javadoc) mentioned above (emphasis mine)
The method does not treat a backslash character, '\', before a non-valid escape character as an error; the backslash is silently dropped. For example, in a Java string the sequence "\z" would cause a compile time error. In contrast, this method silently drops the backslash. Therefore, this method treats the two character sequence "\b" as equivalent to the single character 'b'
For me, I always had trouble with backslashes in the properties file (even with double backslash '\\') unless I specified the unicode.
Replace \ with \\ as below:
c:\sdjf\slkdfj.jpg
to
c:\\sdjf\\slkdfj.jpg
In addition to Bala R's answer I have the following solution to even keep the newline-semantic of backslashes at the end of a line.
Here is my code:
private static Reader preparePropertyFile(File file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
StringBuilder result = new StringBuilder();
String line;
boolean endingBackslash = false;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (endingBackslash) {
// if the line is empty, is a comment or holds a new property
// definition the backslash found at the end of the previous
// line is not for a multiline property value.
if (line.isEmpty()
|| line.startsWith("#")
|| line.matches("^\\w+(\\.\\w+)*=")) {
result.append("\\\\");
}
}
// if a backslash is found at the end of the line remove it
// and decide what to do depending on the next line.
if (line.endsWith("\\")) {
endingBackslash = true;
line = line.substring(0, line.length() - 1);
} else {
endingBackslash = false;
}
result.append(line.replace("\\", "\\\\"));
}
if (endingBackslash) {
result.append("\\\\");
}
return new StringReader(result.toString());
}
private static Properties getProperties(File file) throws IOException {
Properties result = new Properties();
result.load(preparePropertyFile(file));
return result;
}
The following code will help :
BufferedReader metadataReader = new BufferedReader(new InputStreamReader(new FileInputStream("migrateSchemaGenProps.properties")));
Properties props = new Properties();
props.load(new StringReader(IOUtils.getStringFromReader(metadataReader).replace("\\", "/")));
It is not realy a good thing to use backslashes in a property-file, as they are the escape character.
Nevertheless: a Windows user will trend to use them in any path... Therefore, in a single line thanks apache common IO:
params.load(new StringReader(IOUtils.toString(paramFile.toURI(), null).replaceAll("\\\\", "/")));
you triple use the backslash to get one:
for example:
key=value1\\value2
in the properties file will turn to
key=value1\value2
in the java Properties object
Let's say we have a configuration properties class:
#ConfigurationProperties(prefix = "whitespace.test")
public class WhitespaceTestConfig {
private Map<String, String> configs;
public Map<String, String> getConfigs() {
return configs;
}
public void setConfigs(Map<String, String> configs) {
this.configs = configs;
}
}
and we try to configure it with a key with space included in it:
whitespace.test.configs:
Key With Whitespace: "I am a value with whitespace in it"
Seems as through spring can parse this yaml fine, and it is apparently valid yaml. However, spring (SnakeYaml?) removes the spaces in the Key string:
KeyWithWhitespace -> I am a value with whitespace in it
An easy solution is to designate a special character for space and replace it within the application, but I was wondering if spring already handled this in some fashion? Perhaps there is a way to escape a space in the config in such a way that spring (SnakeYaml?) knows the we want to keep it, or perhaps there is a way to configure this?
For the sake of completeness I've tried using single and double quotations as well as \s \b.
Update:
After some additional research I found an example from SnakeYaml repository that seems to indicate that what I'm looking for should be possible: https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-block-mappings
Specifically this example:
# YAML
base armor class: 0
base damage: [4,4]
plus to-hit: 12
plus to-dam: 16
plus to-ac: 0
# Java
{'plus to-hit': 12, 'base damage': [4, 4], 'base armor class': 0, 'plus to-ac': 0, 'plus to-dam': 16}
In the example the spaces persist in the keys. Unfortunately, I'm at a loss with regard to figuring out where the whitespace is actually getting removed.
For map keys with special characters you need to surround the key with '[]' for the key to be used as specified.
So, in your case it will be
whitespace.test.configs:
'[Key With Whitespace]': "I am a value with whitespace in it"
The new binder is much stricter about property names which means you need to surround them in square brackets. Try the following:
shiro:
testMap:
"[/test1]": test1
"[/test2]": test2
Is it possible to name some blocks inside ftl and get them on java side? For example something like with incrorrect syntax maybe
#emailSubject[
This is email subject]
#emailMessage
[Email multi-
line message!!
Hi all]
and java side looks like
template.process("template.ftl", resultModelOrSomethingElse);
String emailSubject = resultModelOrSomethingElse.getEmailSubject();
String emailMessag = resultModelOrSomethingElse.getEmailMessage();
Out-of-the-box, you can do this:
<#assign emailSubject>This is the email subject</#assign>
<#assign emailMessage>
This is the email message...
</#assign>
and then:
// Same as template.process, but you will have the Environment:
Environment env = template.createProcessingEnvironment(dataModel, out);
env.process();
// Extract top-level variables:
TemplateModel emailSubject = env.getVariable("emailSubject");
TemplateModel emailMessage = env.getVariable("emailMessage");
(If it's something that you will do a lot, you might want to streamline this in the template. Like <#emailSubject>This is the email subject</#> is terser and more fool-proof, as it will immediately fail if somebody makes a mistake in the "emailSubject" variable name.)
I Want to parse a double with comma as decimal separator (',' instead of '.') using SuperCSV CellProcessor
I want to parse the first element (0,35) to Double
0,35;40000,45
I have tried something like that :
/** FRENCH_SYMBOLS */
private static final DecimalFormatSymbols FRENCH_SYMBOLS = new DecimalFormatSymbols(Locale.FRANCE);
DecimalFormat df = new DecimalFormat();
df.setDecimalFormatSymbols(FRENCH_SYMBOLS);
final CellProcessor[] processors = new CellProcessor[] {
new NotNull(new ParseDouble(new FmtNumber(df))),
new NotNull(new ParseBigDecimal(FRENCH_SYMBOLS)) };
ParseBigDecimal works just fine but the parseDouble doesn't seems to work, it gives me an exception : org.supercsv.exception.SuperCsvCellProcessorException: '0,35' could not be parsed as a Double
You're totally correct - ParseDouble doesn't support a French-style decimal separator (comma), but ParseBigDecimal does. If you think this is a useful feature, why not submit a feature request.
The simplest workaround is to simply chain a StrReplace before the ParseDouble to convert the comma to full stop.
new StrReplace(",", ".", new ParseDouble())
Alternatively, you could write a custom cell processor that either:
parses a Double (with a configurable decimal separator)
converts a BigDecimal to a Double (calling doubleValue()) - this can then be chained after your new ParseBigDecimal(FRENCH_SYMBOLS)
Oh, and in future you might want to mention that your file is semi-colon separated and you've set up Super CSV with CsvPreference.EXCEL_NORTH_EUROPE_PREFERENCE :)