How can I parse my json file from asset in kotlin? - json

How can I parse my json file in kotlin. There are many solution for this on the internet but all of them are same however I couldnt find to parse my json file in kotlin.
my json file
{
"A": [
{
"collocation": "above average",
"meaning": "more than average, esp. in amount, age, height, weight etc. "
},
{
"collocation": "absolutely necessary",
"meaning": "totally or completely necessary"
},
{
"collocation": "abuse drugs",
"meaning": "to use drugs in a way that's harmful to yourself or others"
},
{
"collocation": "abuse of power",
"meaning": "the harmful or unethical use of power"
}
],
"B": [
{
"collocation": "back pay",
"meaning": "money a worker earned in the past but hasn't been paid yet "
},
{
"collocation": "back road",
"meaning": "a small country road "
},
{
"collocation": "back street",
"meaning": "a street in a town or city that's away from major roads or central areas"
},
{
"collocation": "back taxes",
"meaning": "taxes that weren't paid when they were due"
},
{
"collocation": "bad breath",
"meaning": "breath that doesn't smell nice"
}],
this way it goes up to the letter W.
I want to parse them all by letter.
my data classes
data class Collocations(
val tag:String,
val collocation: List<Collocation>
)
data class Collocation(
val collocation: String,
val meaning: String
)
But I think these data classes are not correct in my opinion or not effective.

You should just need the Collocation class that you provided here. Then the top-level object could be a Map<String, List<Collocation>> so that the letters are dynamic keys instead.
Using Kotlinx Serialization, it could look like this:
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
#Serializable
data class Collocation(
val collocation: String,
val meaning: String,
)
fun main() {
val json: String = TODO("get your JSON string here")
val collocations = Json.decodeFromString<Map<String, List<Collocation>>>(json)
val collocationsForA = collocations["A"]
println(collocationsForA)
}

Related

Generate Data class on dynamic value inside a JSON payload

I have a payload which look like this :
{
"data": {
"12345": {
"is_indexable": true,
"description": "Lorem description",
"items": {
"id": 2644,
"name": "Naming here"
}
},
"678910": {
"is_indexable": false,
"description": "Lorem description 2",
"items": {
"id": 29844,
"name": "Naming here again"
}
}
}
}
I wanted to generate a specific data class for that payload using tools like https://transform.tools/json-to-kotlin but it's impossible since the array inside the "data" object is an ID (so a dynamic data)
data class Root(
val data_field: Data
)
data class Data(
val payload: List<Payload>, // Something to represent the dynamic ids
)
data class Payload(
val isIndexable: Boolean,
val description: String,
val items: Items
)
data class Items(
val id: Long,
val name: String
)
I don't know if I'm clear, did you have an idea to make this in a clean way ?
Thank you all !
You need to array of map to achieve this. You are building map in map right now. It should be like following if you need array;
{
"data": [
{ id: "12345",
"is_indexable": true,
"description": "Lorem description",
"items": {
"id": 2644,
"name": "Naming here"
}
},
{"id" : "678910"
"is_indexable": false,
"description": "Lorem description 2",
"items": {
"id": 29844,
"name": "Naming here again"
}
}
]
}
There is an amazing plugin add to the android studio where it converts this payload to suitable classes
for example, the JSON has one object and inside the object, there are a lot of objects and array this tool will determine all this as classes
you can load it from this link:
https://plugins.jetbrains.com/plugin/9960-json-to-kotlin-class-jsontokotlinclass
From this link, you can also know how you can use this tool
go to android studio and from file->setting->plugin->Install Plugin from disk
enter image description here
and convert it by easy and without problems
good luck

Scala: Map part of Json to Object with playframework

I'm relatively new to Scala. I would like to map part of my Json to my Object. Code looks like this:
def seasons = (json \\ "season")
case class:
case class Season(startDate: LocalDate, endDate: LocalDate)
json-structure:
[
{
"id": "",
"name": "",
"season": {
"start": "0",
"end": "0"
}
}
]
I would somehow like to end up with a List[Season], so I can loop through it.
Question #2
json-structure:
[
{
"id": "",
"name": "",
"season": {
"start": "0",
"end": "0"
}
},
{
"id": "",
"name": "",
"season": {
"start": "0",
"end": "0"
}
}...
]
Json (which is a JsValue btw) brings multiple regions as can be seen above. Case classed are provided (Region holds a Season), naming is the same as in json.
Formats look like this:
implicit val seasonFormat: Format[Season] = Json.format[Season]
implicit val regionFormat: Format[Region] = Json.format[Region]
So what would I need to call in order to get a List[Region]? I thought of something like regionsJson.as[List[Region]] as I defined the Format, which provides me the Read/Write possibilities. But unfortunately, it's not working.
What is the best way doing this? I've tried it with an JsArray, but I have difficulties with mapping it...
Any input would be much appreciated!
I've added some changes to your original case class and renamed its fields to match json fields.
The following code does parsing of the json into Seq[Session]
import java.time.LocalDate
import play.api.libs.json._
case class Season(start: LocalDate, end: LocalDate)
implicit val sessionFormat: Format[Season] = Json.format[Season]
val json =
"""
|[
| {
| "id": "",
| "name": "",
| "season": {
| "start": "2020-10-20",
| "end": "2020-10-22"
| }
| }
|]
|""".stripMargin
val seasonsJson: collection.Seq[JsValue] = Json.parse(json) \\ "season"
val seasons: collection.Seq[Season] = seasonsJson.map(_.as[Season])
seasons.foreach(println)
Please note that I changed the data of your json and instead of 0, which is not a valid date, I provided dates in iso format yyyy-mm-dd.
The above code works with play-json version 2.9.0.
---UPDATE---
Following up comment by #cchantep.
Method as will produce an exception if json cannot be mapped in case class, a non-exception option is to use asOpt that does not throw an exception but returns a None if mapping is not possible.

Transforming JSON with Circe

Suppose I have some JSON data like this:
{
"data": {
"title": "example input",
"someBoolean": false,
"innerData": {
"innerString": "input inner string",
"innerBoolean": true,
"innerCollection": [1,2,3,4,5]
},
"collection": [6,7,8,9,0]
}
}
And I want to flatten it a bit and transform or remove some fields, to get the following result:
{
"data": {
"ttl": "example input",
"bool": false,
"collection": [6,7,8,9,0],
"innerCollection": [1,2,3,4,5]
}
}
How can I do this with Circe?
(Note that I'm asking this as a FAQ since similar questions often come up in the Circe Gitter channel. This specific example is from a question asked there yesterday.)
I've sometimes said that Circe is primarily a library for encoding and decoding JSON, not for transforming JSON values, and in general I'd recommend mapping to Scala types and then defining relationships between those (as Andriy Plokhotnyuk suggests here), but for many cases writing transformations with cursors works just fine, and in my view this kind of thing is one of them.
Here's how I'd implement this transformation:
import io.circe.{DecodingFailure, Json, JsonObject}
import io.circe.syntax._
def transform(in: Json): Either[DecodingFailure, Json] = {
val someBoolean = in.hcursor.downField("data").downField("someBoolean")
val innerData = someBoolean.delete.downField("innerData")
for {
boolean <- someBoolean.as[Json]
collection <- innerData.get[Json]("innerCollection")
obj <- innerData.delete.up.as[JsonObject]
} yield Json.fromJsonObject(
obj.add("boolean", boolean).add("collection", collection)
)
}
And then:
val Right(json) = io.circe.jawn.parse(
"""{
"data": {
"title": "example input",
"someBoolean": false,
"innerData": {
"innerString": "input inner string",
"innerBoolean": true,
"innerCollection": [1,2,3]
},
"collection": [6,7,8]
}
}"""
)
And:
scala> transform(json)
res1: Either[io.circe.DecodingFailure,io.circe.Json] =
Right({
"data" : {
"title" : "example input",
"collection" : [
6,
7,
8
]
},
"boolean" : false,
"collection" : [
1,
2,
3
]
})
If you look at it the right way, our transform method kind of resembles a decoder, and we can actually write it as one (although I'd definitely recommend not making it implicit):
import io.circe.{Decoder, Json, JsonObject}
import io.circe.syntax._
val transformData: Decoder[Json] = { c =>
val someBoolean = c.downField("data").downField("someBoolean")
val innerData = someBoolean.delete.downField("innerData")
(
innerData.delete.up.as[JsonObject],
someBoolean.as[Json],
innerData.get[Json]("innerCollection")
).mapN(_.add("boolean", _).add("collection", _)).map(Json.fromJsonObject)
}
This can be convenient in some situations where you want to perform the transformation as part of a pipeline that expects a decoder:
scala> io.circe.jawn.decode(myJsonString)(transformData)
res2: Either[io.circe.Error,io.circe.Json] =
Right({
"data" : {
"title" : "example input",
"collection" : [ ...
This is also potentially confusing, though, and I've thought about adding some kind of Transformation type to Circe that would encapsulate transformations like this without questionably repurposing the Decoder type class.
One nice thing about both the transform method and this decoder is that if the input data doesn't have the expected shape, the resulting error will include a history that points to the problem.

Groovy - JsonSlurper Parsing JSON file

I have a JSON document structured similar to below, and I am trying to parse it in Groovy. Basically for each School (School Info), I want to grab the SCHOOL_COUNTRY and other fields. I am trying this code below but it is not returning what I need. For each school listed (1,000's), I want to grab only specific parts, for instance:
def parseJSON(long id) {
JSONFile fileInstance = JSONFile.get(id)
def json = new JsonSlurper().setType(RELAX).parse(new FileReader(fileInstance.filePath))
def schoolInfo = json.SCHOOL_INFO
def schoolName = json.SCHOOL_INFO.SCHOOL_NAME
schoolInfo.each {
render(schoolInfo.SCHOOL_NAME)
}
}
So basically for each school, just print out the name of the school. The JSON structure:
[{
"SCHOOL_INFO": {
"SCHOOL_COUNTRY": "Finland",
"SCHOOL NAME": "Findland Higher Learning"
},
"LOCATION": {
"LONGITUDE": "24.999",
"LATITUDE": "61.001"
}
}]
I'm not sure if it's the only bug but you can't read schoolInfo.SCHOOL_NAME in each. SCHOOL_NAME is property of json.SCHOOL_INFO so it.SCHOOL_NAME is proper way to access it. Take look at example below:
import groovy.json.JsonSlurper
def jsonAsText = '''[{
"SCHOOL_INFO": {
"SCHOOL_COUNTRY": "Finland",
"SCHOOL NAME": "Findland Higher Learning"
},
"LOCATION": {
"LONGITUDE": "24.999",
"LATITUDE": "61.001"
}
}]'''
def json = new JsonSlurper().parseText(jsonAsText)
def schoolInfo= json.SCHOOL_INFO
schoolInfo.each{
println it."SCHOOL NAME"
}
It prints:
Findland Higher Learning
Here You go:
import groovy.json.JsonSlurper
def t = """[{
"SCHOOL_INFO": {
"SCHOOL_COUNTRY": "Finland",
"SCHOOL NAME": "Findland Higher Learning"
},
"LOCATION": {
"LONGITUDE": "24.999",
"LATITUDE": "61.001"
}
}]"""
def slurper = new JsonSlurper().parseText(t)
slurper.each {
println it.SCHOOL_INFO."SCHOOL NAME"
}
I'm not sure if there should be _ sign in SCHOOL NAME.
println it.SCHOOL_INFO."SCHOOL NAME"
This should work without _ sign.

How to parse ObjectId (MongoDB) in JSON that is sent to Grails Server

I have searched many post here but I still couldn't find the answer yet.
Problem:
I want to parse this JSON:
{
"price": {
"currency": {
"class": "com.yintagoka.ad.Currency",
"id": {
"class": "org.bson.types.ObjectId",
"inc": -612166639,
"machine": -1775927134,
"new": false,
"time": 1393682821000,
"timeSecond": 1393682821
},
"code": "USD",
"longName": "United States Dollar",
"name": "USD",
"symbol": null
},
"amount": 100
},
"title": "title",
"description": "desc"
}
to become an Object in my Grails server
class House {
ObjectId id
String name
String title
Price price
// ... many more
}
class Price {
BigDecimal amount
Currency currency
}
class Currency {
ObjectId id
String code
String longName
String name
String symbol
}
Grails did almost all the heavy stuff for me, but it can't generate the ObjectId. So I will have Object Currency with all the property name filled with the value but the id will be null.
How can I tell Grails to render the ObjectId as well, preferably automatically.
Note: I don't want to use String for my id.
I also read a post that I can set it manually by request.JSON, but the problem is that I always get an empty map.
def save(House house) {
print('request = '+request.JSON)
print('house = '+house)
print('params = '+params)
}
out:
request = [:]
house = com.yintagoka.ad.House#217b1ead[id=<null>,title=title,description=desc,price=com.yintagoka.ad.Price#1a1b0107[amount=100,currency=com.yintagoka.ad.Currency#62e07ff4[id=<null>,name=USD,longName=United States Dollar,code=USD,symbol=<null>]]
params = [action:delete, controller:house]