I am getting this format from a json string:
ABCD\n EFG: HIJKL\n
MNO: PQRST \n\n
UVW: XYZ
When I print it, the line breaks ("\n") is not inserted. I get the Json string like so:
val orReply = gson.fromJson<OrReply>(decryptedValue, OrReply::class.java)
printReceipt(orReply.ORData)
and use this reply as so:
private fun printReceipt(orString: String) {
printOnPrinter(orString)
}
Try the following function to process the line breaks and see if helps you in fixing the issue:
private fun processLineBreak(string: String) : String{
return string.replace("\n",System.lineSeparator())
}
Related
Goal:
I am trying to parse the postman_echo collection json and persist the result into a new json copy on disk, resulting the same file as the original one.
I prefer built-in data structure from the language, but using json library should be good too. Not sure Antlr4 is a better way.
follow-up question
is it possible to allow any valid nested json in the body of post request?
update:
https://github.com/chakpongchung/postman-parser
In the end we come up with this satisfactory solution.
An alternative to what zoran mentioned is to create a case class if the structure is not too dynamic (with Play JSON). This would make it easier to compare the result.
case class MyObject(
queryString: List[KeyValue],
method: String,
url: String,
httpVersion: String
) ... and so on
object MyObject {
implicit val format: Format[MyObject] = Json.format
}
case class KeyValue(name: String, value: String)
object KeyValue {
implicit val format: Format[KeyValue] = Json.format
}
Then, you just need to do:
object JsonParser extends App {
val postman_collections = "./scala_input.json"
val jsonifiedString = scala.io.Source.fromFile(postman_collections).mkString
val myJsonData = Try(Json.parse(jsonifiedString)).map(_.as[MyObject])
myJsonData match {
case Success(myValue) => // compare your case class here
case Failure(err) => println("none")
}
}
I'm not sure if I understand your question well, but if you are trying to iterate over json string, you might try something like this:
import play.api.libs.json.{JsObject, JsValue, Json}
import scala.util.{Failure, Success, Try}
object JsonParser extends App {
val postman_coolections = "./resources/scala_input.json"
val jsonifiedString = scala.io.Source.fromFile(postman_coolections).mkString
val json: JsValue = Try(Json.parse(jsonifiedString)) match {
case Success(js) => js
case Failure(ex) => throw new Exception("Couldn't parse json", ex)
}
json.asInstanceOf[JsObject].fields.foreach{
case (key: String, value: JsValue)=>
println(s"Key:$key value:${value.toString}")
writeFile(s"$key.json", Json.prettyPrint(value))
}
//writing the whole postman input as a single file
writeFile("postmanInputFormatted.json", Json.prettyPrint(json))
writeFile("postmanInput.json", Json.stringify(json))
// To access individual property one option is to use this approach
val lookedValue = json \ "postData" \ "params" \ 1 \ "hello" \ "test"
lookedValue match {
case JsDefined(value) => println(s"Test value is $value")
case JsUndefined() => println("Didn't find test value")
}
// or
val lookedValueAlt = (json \ "postData" \ "params" \ 1 \ "hello" \ "test").getOrElse(throw SomeException)
There are multiple problems in your parser and most of them are that you are trying to use default parser to handle Json object as string. For example, in Request you are handling header as Seq[String] when it's actually Seq of (key, value) pairs. For this particular case, you should change it to something like this:
case class Request(
method: String,
header: Seq[HeaderItem], // header: []
url: Option[Url] = None,
description: String = ""
)
object Request {
implicit val format: Format[Request] = Json.using[Json.WithDefaultValues].format
case class HeaderItem(key: String, value: String)
object HeaderItem {
implicit val format: Format[HeaderItem] = Json.format
}
You can convert header to Seq[String] if you want, but you will have to write custom Read for that.
In the above case you also have cases when description is missing, so you want to handle that with default values.
You have such problems to handle in few other places as well, e.g. "response".
Another problem that I've noticed is a way how you handle "type" property from Json string. Type is reserved keyword, and you can handle it by wrapping it in ``, e.g.
case class Script(
`type`: String,
exec: Seq[String]
)
A satisfactory solution is posted in the github link above in the question.
Given a grammar (simplified version below) where I can enter arbitrary text in a section of the grammar, is it possible to format the content of the arbitrary text? I understand how to format the position of the arbitrary text in relation to the rest of the grammar, but not whether it is possible to format the content string itself?
Sample grammar
Model:
'content' content=RT
terminal RT: // (returns ecore::EString:)
'RT>>' -> '<<RT';
Sample content
content RT>>
# Some sample arbitrary text
which I would like to format
<<RT
you can add custom ITextReplacer to the region of the string.
assuming you have a grammar like
Model:
greetings+=Greeting*;
Greeting:
'Hello' name=STRING '!';
you can do something like the follow in the formatter
def dispatch void format(Greeting model, extension IFormattableDocument document) {
model.prepend[newLine]
val region = model.regionFor.feature(MyDslPackage.Literals.GREETING__NAME)
val r = new AbstractTextReplacer(document, region) {
override createReplacements(ITextReplacerContext it) {
val text = region.text
var int index = text.indexOf(SPACE);
val offset = region.offset
while (index >=0){
it.addReplacement(region.textRegionAccess.rewriter.createReplacement(offset+index, SPACE.length, "\n"))
index = text.indexOf(SPACE, index+SPACE.length()) ;
}
it
}
}
addReplacer(r)
}
this will turn this model
Hello "A B C"!
into
Hello "A
B
C"!
of course you need to come up with a more sophisticated formatter logic.
see How to define different indentation levels in the same document with Xtext formatter too
In Android it is possible to use placeholders in strings, such as:
<string name="number">My number is %1$d</string>
and then in Java code (inside a subclass of Activity):
String res = getString(R.string.number);
String formatted = String.format(res, 5);
or even simpler:
String formatted = getString(R.string.number, 5);
It is also possible to use some HTML tags in Android string resources:
<string name="underline"><u>Underline</u> example</string>
Since the String itself cannot hold any information about formatting, one should use getText(int) instead of getString(int) method:
CharSequence formatted = getText(R.string.underline);
The returned CharSequence can be then passed to Android widgets, such as TextView, and the marked phrase will be underlined.
However, I could not find how to combine these two methodes, using formatted string together with placeholders:
<string name="underlined_number">My number is <u>%1$d</u></string>
How to process above resource in the Java code to display it in a TextView, substituting %1$d with an integer?
Finally I managed to find a working solution and wrote my own method for replacing placeholders, preserving formatting:
public static CharSequence getText(Context context, int id, Object... args) {
for(int i = 0; i < args.length; ++i)
args[i] = args[i] instanceof String? TextUtils.htmlEncode((String)args[i]) : args[i];
return Html.fromHtml(String.format(Html.toHtml(new SpannedString(context.getText(id))), args));
}
This approach does not require to escape HTML tags manually neither in a string being formatted nor in strings that replace placeholders.
Kotlin extension function that
works with all API versions
handles multiple arguments
Example usage
textView.text = context.getText(R.string.html_formatted, "Hello in bold")
HTML string resource wrapped in a CDATA section
<string name="html_formatted"><![CDATA[ bold text: <B>%1$s</B>]]></string>
Result
bold text: Hello in bold
Code
/**
* Create a formatted CharSequence from a string resource containing arguments and HTML formatting
*
* The string resource must be wrapped in a CDATA section so that the HTML formatting is conserved.
*
* Example of an HTML formatted string resource:
* <string name="html_formatted"><![CDATA[ bold text: <B>%1$s</B> ]]></string>
*/
fun Context.getText(#StringRes id: Int, vararg args: Any?): CharSequence =
HtmlCompat.fromHtml(String.format(getString(id), *args), HtmlCompat.FROM_HTML_MODE_COMPACT)
<resources>
<string name="welcome_messages">Hello, %1$s! You have <b>%2$d new messages</b>.</string>
</resources>
Resources res = getResources();
String text = String.format(res.getString(R.string.welcome_messages), username, mailCount);
CharSequence styledText = Html.fromHtml(text);
More Infos here: http://developer.android.com/guide/topics/resources/string-resource.html
For the simple case where you want to replace a placeholder without number formatting (i.e. leading zeros, numbers after comma) you can use Square Phrase library.
The usage is very simple: first you have to change the placeholders in your string resource to this simpler format:
<string name="underlined_number">My number is <u> {number} </u></string>
then you can make the replacement like this:
CharSequence formatted = Phrase.from(getResources(), R.string.underlined_number)
.put("number", 5)
.format()
The formatted CharSequence is also styled. If you need to format your numbers, you can always pre-format them using String.format("%03d", 5) and then use the resulting string in the .put() function.
This is the code that finally worked for me
strings.xml
<string name="launch_awaiting_instructions">Contact <b>our</b> team on %1$s to activate.</string>
<string name="support_contact_phone_number"><b>555 555 555</b> Opt <b>3</b></string>
Kotlin code
fun Spanned.toHtmlWithoutParagraphs(): String {
return HtmlCompat.toHtml(this, HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
.substringAfter("<p dir=\"ltr\">").substringBeforeLast("</p>")
}
fun Resources.getText(#StringRes id: Int, vararg args: Any): CharSequence {
val escapedArgs = args.map {
if (it is Spanned) it.toHtmlWithoutParagraphs() else it
}.toTypedArray()
val resource = SpannedString(getText(id))
val htmlResource = resource.toHtmlWithoutParagraphs()
val formattedHtml = String.format(htmlResource, *escapedArgs)
return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
Using this I was able to render styled text on Android with styled placeholders too
Output
Contact our team on 555 555 555 Opt 3 to activate.
I was then able to expand on this solution to create the following Compose methods.
Jetpack Compose UI
#Composable
fun annotatedStringResource(#StringRes id: Int, vararg formatArgs: Any): AnnotatedString {
val resources = LocalContext.current.resources
return remember(id) {
val text = resources.getText(id, *formatArgs)
spannableStringToAnnotatedString(text)
}
}
#Composable
fun annotatedStringResource(#StringRes id: Int): AnnotatedString {
val resources = LocalContext.current.resources
return remember(id) {
val text = resources.getText(id)
spannableStringToAnnotatedString(text)
}
}
private fun spannableStringToAnnotatedString(text: CharSequence): AnnotatedString {
return if (text is Spanned) {
val spanStyles = mutableListOf<AnnotatedString.Range<SpanStyle>>()
spanStyles.addAll(text.getSpans(0, text.length, UnderlineSpan::class.java).map {
AnnotatedString.Range(
SpanStyle(textDecoration = TextDecoration.Underline),
text.getSpanStart(it),
text.getSpanEnd(it)
)
})
spanStyles.addAll(text.getSpans(0, text.length, StyleSpan::class.java).map {
AnnotatedString.Range(
SpanStyle(fontWeight = FontWeight.Bold),
text.getSpanStart(it),
text.getSpanEnd(it)
)
})
AnnotatedString(text.toString(), spanStyles = spanStyles)
} else {
AnnotatedString(text.toString())
}
}
Similar to the accepted answer, I attempted to write a Kotlin extension method for this.
Here's the accepted answer in Kotlin
#Suppress("DEPRECATION")
fun Context.getText(id: Int, vararg args: Any): CharSequence {
val escapedArgs = args.map {
if (it is String) TextUtils.htmlEncode(it) else it
}.toTypedArray()
return Html.fromHtml(String.format(Html.toHtml(SpannedString(getText(id))), *escapedArgs))
}
The problem with the accepted answer, is that it doesn't seem to work when the format arguments themselves are styled (i.e. Spanned, not String). By experiment, it seems to do weird things, possibly to do with the fact that we're not escaping non-String CharSequences. I'm seeing that if I call
context.getText(R.id.my_format_string, myHelloSpanned)
where R.id.my_format_string is:
<string name="my_format_string">===%1$s===</string>
and myHelloSpanned is a Spanned that looks like <b>hello</b> (i.e. it would have HTML <i><b>hello</b></i>) then I get ===hello=== (i.e. HTML ===<b>hello</b>===).
That is wrong, I should get ===<b>hello</b>===.
I tried to fix this by converting all CharSequences to HTML before applying String.format, and here is my resulting code.
#Suppress("DEPRECATION")
fun Context.getText(#StringRes resId: Int, vararg formatArgs: Any): CharSequence {
// First, convert any styled Spanned back to HTML strings before applying String.format. This
// converts the styling to HTML and also does HTML escaping.
// For other CharSequences, just do HTML escaping.
// (Leave any other args alone.)
val htmlFormatArgs = formatArgs.map {
if (it is Spanned) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.toHtml(it, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
} else {
Html.toHtml(it)
}
} else if (it is CharSequence) {
Html.escapeHtml(it)
} else {
it
}
}.toTypedArray()
// Next, get the format string, and do the same to that.
val formatString = getText(resId);
val htmlFormatString = if (formatString is Spanned) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.toHtml(formatString, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
} else {
Html.toHtml(formatString)
}
} else {
Html.escapeHtml(formatString)
}
// Now apply the String.format
val htmlResultString = String.format(htmlFormatString, *htmlFormatArgs)
// Convert back to a CharSequence, recovering any of the HTML styling.
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(htmlResultString, Html.FROM_HTML_MODE_LEGACY)
} else {
Html.fromHtml(htmlResultString)
}
}
However, this didn't quite work because when you call Html.toHtml it puts <p> tags around everything even when that extra padding wasn't in the input. Said another way, Html.fromHtml(Html.toHtml(myHelloSpanned)) is not equal to myHelloSpanned - it's got extra padding. I didn't know how to resolve this nicely.
Update: this answer https://stackoverflow.com/a/56944152/6007104 has been updated, and is now the preferred answer
Here's a more readable Kotlin extension which doesn't use deprecated APIs, works on all Android versions, and doesn't require strings to be wrapped in CDATA sections:
fun Context.getText(id: Int, vararg args: Any): CharSequence {
val escapedArgs = args.map {
if (it is String) TextUtils.htmlEncode(it) else it
}.toTypedArray()
val resource = SpannedString(getText(id))
val htmlResource = HtmlCompat.toHtml(resource, HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
val formattedHtml = String.format(htmlResource, *escapedArgs)
return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
You can add an alias as as extension of Fragment - just remember to spread the args in between:
fun Fragment.getText(id: Int, vararg args: Any) = requireContext().getText(id, *args)
You can use java.lang.String for string formatting in Kotlin
fun main(args : Array<String>) {
var value1 = 1
var value2 = "2"
var value3 = 3.0
println(java.lang.String.format("%d, %s, %6f", value1, value2, value3))
}
As a follow up on my previous question: Why doesn't my attempt to escape quotation marks in JSON work?, I would like to know if there is any way to make Gson and Javascript play along when escaping special characters and symbols.
Consider this as a database table string, that I want to display on a web page:
I am "literally" hurting inside because this do not work!
If I retrieve the string in Java from my database, and use Gson to parse it, it will look like this:
'{"text" : "I am \"literally\" hurting inside that this does not work!"}'
However, my Javascript function for parsing needs this to display it correctly:
'{"text" : "I am \\"literally\\" hurting inside that this does not work!"}'
Are there any way to fix this, other then to check for substrings in Java, and adding an extra \?
I would suggest you to use Unbescape [ http://www.unbescape.org ]
It allows you to escape JavaScript string literals (among other things like HTML, XML, JSON...), so you can pass you GSON string to it simply like:
final String escaped = JavaScriptEscape.escapeJavaScript(text);
And it will give you the JavaScript-escaped string you need.
Disclaimer, per StackOverflow rules: I'm Unbescape's author.
Try this one, it will work in all the cases:
{\"text\" : \"I am \\\"litteraly\\\" hurting inside that this does not work!\"}
Sample code:
Using JSONObject:
String str = "{\"text\" : \"I am \\\"litteraly\\\" hurting inside that this does not work!\"}";
try {
System.out.println(new JSONObject(str).getString("text"));
} catch (JSONException e) {
e.printStackTrace();
}
Using Gson:
class Text implements Serializable{
private String text;
...
}
Gson gson = new Gson();
String str = "{\"text\" : \"I am \\\"litteraly\\\" hurting inside that this does not work!\"}";
System.out.println(gson.fromJson(str, Text.class).text);
Firefox Firebug plugin snapshot:
String str = "{\"text\" : \"I am \\\"litteraly\\\" hurting inside that this does not work!\"}";
try {
System.out.println(new JSONObject(str).getString("text"));
} catch (JSONException e) {
e.printStackTrace();
}
Need a quick help. I am a newbie in QuickFixJ. I have a FIX message in a txt file. I need to convert that into FIX50SP2 format. I am enclosing the code snippet.
String fixMsg = "1128=99=25535=X49=CME34=47134052=20100318-03:21:11.36475=20120904268=2279=122=848=336683=607400107=ESU2269=1270=140575271=152273=121014000336=2346=521023=1279=122=848=336683=607401107=ESU2269=1270=140600271=206273=121014000336=2346=681023=210=159";
System.out.println("FixMsg String:"+fixMsg);
Message FIXMessage = new Message();
DataDictionary dd = new DataDictionary("FIX50SP2.xml");
FIXMessage.fromString(fixMsg, dd, false);
System.out.println("FIXMessage Output:" + FIXMessage.toString()); // Print message after parsing
MsgType msgType = new MsgType();
System.out.println(FIXMessage.getField(msgType));
Here is the output:
FixMsg String:1128=99=15835=X49=CME34=47164052=2012090312102051175=20120904268=1279=122=848=336683=607745107=ESU2269=1270=140575271=123273=121020000336=2346=501023=110=205
FIXMessage Output:9=6135=X34=47164049=CME52=2012090312102051175=20120904268=110=117
quickfix.FieldNotFound: Field [35] was not found in message.
at quickfix.FieldMap.getField(FieldMap.java:216)
at quickfix.FieldMap.getFieldInternal(FieldMap.java:353)
at quickfix.FieldMap.getField(FieldMap.java:349)
at MainApp.main(MainApp.java:52)
I want to extract MsgType field (field 35). Could you please tell me where I am wrong? The thing I have observed is that after parsing to FIX50SP2 format, the convert FIX message is missing many data element (for details see the output)
Thanks
Like others mentioned the MsgType is an header field and you get it by using the following
String msgType = null;
if(FIXMessage.getHeader().isSetField(MsgType.FIELD)) {
msgType = FIXMessage.getHeader().getString(MsgType.FIELD);
}
System.out.println("MsgType is " + msgType);`
The reason you are missing many data element after parsing is, probably your message have some custom tags(like tag 2346), which is not defined in your data dictionary(FIXSP02.xml). hence the parsing of those tags failed and missing in the output.
To fix this, get the data dictionary from the party that is sending you the message and use it to parse the message
I'm not familiar with FIX messages and QuickFixJ, but glancing at the Javadoc, it seems like you should use the identifyType method :
String fixMsg = "1128=99=25535=X49=CME34=47134052=20100318-03:21:11.36475=20120904268=2279=122=848=336683=607400107=ESU2269=1270=140575271=152273=121014000336=2346=521023=1279=122=848=336683=607401107=ESU2269=1270=140600271=206273=121014000336=2346=681023=210=159";
MsgType msgType = Message.identifyType(fixMsg);
You may find FixB framework useful as it deals well with non-standard use cases of FIX.
As in your case, to extract only data you are interested in, you need to define a class that will represent this data and to bind it to FIX using annotations. E.g.:
#FixBlock
public class MDEntry {
#FixField(tag=269) public int entryType; // you could define an enum type for it as well
#FixField(tag=278) public String entryId;
#FixField(tag=55) public String symbol;
}
...
FixFieldExtractor fixExtractor = new NativeFixFieldExtractor();
List<MDEntry> mdEntries = fixExtractor.getGroups(fixMsg, List.class, 268, FixMetaScanner.scanClass(MDEntry.class))
In more common cases, FixSerializer interface should be used, but it requires a message with MsgType(35) tag and a class annotated with #FixMessage(type="...") accordingly. E.g.:
#FixMessage(type="X")
public class MarketData {
#FixGroup(tag=268) public List<MDEntry> entries;
}
...
FixMetaDictionary fixMetaDictionary = FixMetaScanner.scanClassesIn("my.fix.classes.package");
FixSerializer fixSerializer = new NativeFixSerializer("FIX.5.0.SP2", fixMetaDictionary);
MarketData marketData = fixSerializer.deserialize(fixMsg);
I hope you will find it useful.
If you need just a MsgTyp, you're sure the message is correct and you do not need any other field from the message, then I would recommend extracting MsgType from string using regexp.
e.g.: \u000135=(\w+)\u0001
It is MUCH FASTER than parsing (and validating) a string via QuickFix.