I want to return the value "stations" from the key "base" in the JSON below from the url https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22. How do I do that in Scala?
Here is what I attempted.
import scalaj.http._
import play.api.libs.json.{JsValue, Json}
object JSON {
def convertToJson(): String = {
val url: String = "https://samples.openweathermap.org/data/2.5/weather?q=London,uk&appid=b6907d289e10d714a6e88b30761fae22"
val response: String = Http(url).asString.body
val parsed: JsValue = Json.parse(response)
parsed.get(base)
}
}
You can use \ method returning a property corresponding a field name
val result: JsLookupResult = parsed \ "base"
If you want the result as string you can use as[String] conversion
println(result.as[String])
It will print "station", but it can throw an exception if it isn't really String
In case if value is missing you can use pattern matching:
result match {
case JsDefined(v) => println(v.toString) // will print "stations"
case undefined: JsUndefined => println(undefined.validationError) // prints error in case missing value
}
Related
I have json string as below i want to convert to object
{"Init":{"MOP":[{"Id":"1","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXB","TerminalId":"P400Plus-275008565","IP":"10.0.0.0:900","Currency":"EUR"},{"Id":"2","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXF","TerminalId":"P400Plus-275008565","IP":"10.0.0.0:901","Currency":"EUR"}]}}
My json is valid , i tried on here also i created POJO class on here but i'm getting com.google.gson.stream.MalformedJsonException
Here my code
val receiveString = "{"Init":{"MOP":[{"Id":"1","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXB","TerminalId":"P400Plus-275008565","IP":"10.0.0.0:900","Currency":"EUR"},{"Id":"2","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXF","TerminalId":"P400Plus-275008565","IP":"10.0.0.0:901","Currency":"EUR"}]}}"
val root = gson.fromJson(receiveString,TestClass.Root::class.java) //getting error here
Here my POJO class
class Root {
#JsonProperty("Init")
var init: Init? = null
}
class MOP {
#JsonProperty("Id")
var id: String? = null
#JsonProperty("Type")
var type: String? = null
#JsonProperty("ProtocolVersion")
var protocolVersion: String? = null
#JsonProperty("MopCode")
var mopCode: String? = null
#JsonProperty("TerminalId")
var terminalId: String? = null
#JsonProperty("IP")
var ip: String? = null
#JsonProperty("Currency")
var currency: String? = null
}
class Init {
#JsonProperty("MOP")
var mop: List<MOP>? = null
}
What yu can suggest me?
doubleQuote (") in your string must be escaped like "
I solved my problem with adding extra quotes missing parts as below
{"Init":{"MOP":[{"Id":"1","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXB","TerminalId":"'P400Plus-275008565'","IP":"'192.168.1.15'","Currency":"EUR"},{"Id":"2","Type":"0","ProtocolVersion":"1.0","MopCode":"*NEXF","TerminalId":"'P400Plus-275008565'","IP":"'10.0.0.0:901'","Currency":"EUR"}]}}
I have Java code to receive data in Android App via Bluetooth like the attached code
Java Code
so readMessage will equal = {\"Pin\":\"A4\",\"Value\":\"20\"},{\"Pin\":\"A5\",\"Value\":\"925\"},{\"Pin\":\"A0\",\"Value\":\"30\"}
So I want to take only the values after string \"Value\" from received data so
Can anyone suggest how to make do that?
Thanks
you can parse the readMessage with JSON format
example:
String[] pinValueArr = readMessage.split(",")
for (String pinValue : pinValueArr) {
try {
JSONObject pinValueJSON = new JSONObject(pinValue);
String pin = pinValueJSON.optString("pin", ""); // opt means if parse failed, return default value what is ""
int pin = pinValueJSON.optInt("Value", 0); // opt means if parse failed, return default value what is "0"
} catch (JSONParsedException e) {
// catch exception when parse to JSONObject failed
}
}
And if you want to manage them, you can make a List and add them all.
List<JSONObject> pinValueList = new ArrayList<JSONObject>();
for (String pinValue : pinValueArr) {
JSONObject pinValueJSON = new JSONObject(pinValue);
// ..
pinValueList.add(pinValueJSON);
}
You can use Gson to convert Json to Object.
(https://github.com/google/gson)
Create Model Class
data class PinItem(
#SerializedName("Pin")
val pin: String? = null,
#SerializedName("Value")
val value: String? = null
)
Convert your json.
val json = "[{"Pin":"A4","Value":"20"},{"Pin":"A5","Value":"925"},{"Pin":"A0","Value":"30"}]"
val result = Gson().fromJson(this, object : TypeToken<List<PinItem>>() {}.type)
So now you having list PinItem and you can get all info off it.
I have a mutableMap,
val invoiceAdditionalAttribute = mutableMapOf<String, Any?>()
invoiceAdditionalAttribute.put("clinetId",12345)
invoiceAdditionalAttribute.put("clientName", "digital")
invoiceAdditionalAttribute.put("payload", "xyz")
I want to convert it into json string
the output should be,
"{\"clinetId\"=\"12345\", \"clientName\"=\"digital\", \"payload\"=\"xyz\"}"
Currently, I am using Gson library,
val json = gson.toJson(invoiceAdditionalAttribute)
and the output is
{"clinetId":12345,"clientName":"digital","payload":"xyz"}
The right json formatting string is:
{"clinetId":12345,"clientName":"digital","payload":"xyz"}
So this is the right method to get it:
val json = gson.toJson(invoiceAdditionalAttribute)
If you want a string formatted like this:
{"clinetId"=12345, "clientName"="digital", "payload"="xyz"}
just replace : with =:
val json = gson.toJson(invoiceAdditionalAttribute).replace(":", "=")
But if you truly want to have a string with backslashes and clinetId value to be inside quotes:
val invoiceAdditionalAttribute = mutableMapOf<String, Any?>()
invoiceAdditionalAttribute["clinetId"] = 12345.toString()
invoiceAdditionalAttribute["clientName"] = "digital"
invoiceAdditionalAttribute["payload"] = "xyz"
val json = gson.toJson(invoiceAdditionalAttribute)
.replace(":", "=")
.replace("\"", "\\\"")
EDIT:
As pointed int he comments .replace(":", "=") can be fragile if some string values contain a ":" character.
To avoid it I would write a custom extension function on Map<String, Any?>:
fun Map<String, Any?>.toCustomJson(): String = buildString {
append("{")
var isFirst = true
this#toCustomJson.forEach {
it.value?.let { value ->
if (!isFirst) {
append(",")
}
isFirst = false
append("\\\"${it.key}\\\"=\\\"$value\\\"")
}
}
append("}")
}
// Using extension function
val customJson = invoiceAdditionalAttribute.toCustomJson()
I'm using Jackson to parse json string to scala case class instance.
Here's my code
import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import scala.reflect.{ClassTag, _}
object JsonUtil {
val jacksonMapper = new ObjectMapper()
jacksonMapper.registerModule(DefaultScalaModule)
jacksonMapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, false)
jacksonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
def toJson(value: Map[Symbol, Any]): String = {
toJson(value map { case (k,v) => k.name -> v})
}
def toJson(value: Any): String = {
jacksonMapper.writeValueAsString(value)
}
def fromJson[T: ClassTag](json: String): T = {
jacksonMapper.readValue[T](json, classTag[T].runtimeClass.asInstanceOf[Class[T]])
}
}
and this's the json parsing error
case class Person(name: String, age: Long, score: List[Long])
val person = JsonUtil.fromJson[Person]("""{"name": 123654,"age":23, "score": [6,7,9]}""")
person.name
person.score
person.score.head
res0: String = 123654
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
at scala.runtime.BoxesRunTime.unboxToLong(ws.sc93376:101)
at #worksheet#.#worksheet#(ws.sc93376:35)
I know jackson is smart enough to convert between numeric types, string to numeric and vice versa, but seemingly it only works for non-collection situation.
How can I do better, that forces jackson recursively converts type inside collection?
You have to add this annotation before score: List[Long]:
#JsonDeserialize(contentAs = classOf[java.lang.Long])
Source: https://github.com/FasterXML/jackson-module-scala/wiki/FAQ
I have an integer value, say int id whose value i get runtime by getter function.
I want to replace this value of id in place of "VALUE" from .json like as follows
{
"id":"VALUE",
"name": "Name updated",
"description": "description Updated",
"active": false
}
I found following way to replace it if id is String,
String str = "myJson.json";
str.replace("\"VALUE\"", "\"id\"");
How can i use int id in above function with this format "\"id\"" ?
Any other solution are welcome.
EDIT:
String str = "myJson.json";
is wrong way to get json content into String.
You can do it with simple regex replace, e.g.:
public static void main(String[] args) {
String value = "{\"id\":\"VALUE\",\"name\": \"Name updated\",\"description\": \"description Updated\",\"active\": false}";
int id = 5;
value = value.replaceAll("\"VALUE\"", String.valueOf(id));
System.out.println(value);
}
Using org.json library you can assign it to JSON Object and Use the put method:
JSONObject jsonObject= new JSONObject(YOUR_STRING);
String[] names = JSONObject.getNames(jsonObject);
JSONArray jsonArray = jsonObject.toJSONArray(new JSONArray(names));
JSONObject id= jsonArray.getJSONObject(0).getJSONObject("id");
person.put("VALUE", id);
regex replace may create some issue by replace someother matching string .
I did in following way.
To replace content of Json file need to convert contents in to String. I did this with help of following function.
public static String loadJson(String jsonFileName) throws IOException {
InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(jsonFileName);
return IOUtils.toString(stream);
}
Then declare a String variable,
String editedJson = loadJson(TEST_SET + "myJson.json");
editedJson.replace("VALUE", "" + id);