Create custom json definition in play scala - scala

I'm new to Scala and I'm learning Scala and Play Framework:
I'm trying to dynamically create a Json with play/scala starting from a sequence of data named "tables" by using Map(...), List(...) and Json.toJson(...).
My result should be like the code resultCustomJsonData shown below
var resultCustomJsonData = [
{
text: "Parent 1",
nodes: [
{
text: "Child 1",
nodes: [
{
text: "Grandchild 1"
},
{
text: "Grandchild 2"
}
]
},
{
text: "Child 2"
}
]
},
{
text: "Parent 2"
},
{
text: "Parent 3"
},
{
text: "Parent 4"
},
{
text: "Parent 5"
}
];
my scala code is this below:
val customJsonData = Json.toJson(
tables.map { t => {
Map(
"text" -> t.table.name.name, "icon" -> "fa fa-cube", "nodes" -> List (
Map( "text" -> "properties" )
)
)
}}
)
but i'm getting this error:
No Json serializer found for type Seq[scala.collection.immutable.Map[String,java.io.Serializable]]. Try to implement an implicit Writes or Format for this type.

Here is a way to do it without using temporary Map:
import play.api.libs.json.Json
val customJsonData = Json.toJson(
tables.map { t =>
Json.obj(
"text" -> t.table.name.name,
"icon" -> "fa fa-cube",
"nodes" -> Json.arr(Json.obj("text" -> "properties"))
)
}
)

I think you should try implement custom serializer/writer. Check here.
For example:
implicit val userWrites = new Writes[User] {
def writes(user: User) = Json.obj(
"id" -> user.id,
"email" -> user.email,
"firstName" -> user.firstName,
"lastName" -> user.lastName
)
}

Related

Get polymorphic model with spring boot, mongodb and kotlin

I am saving a polymorphic model using mongoDB, and the data is saved perfectly, for example.
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY, property = "type", visible = true)
#JsonSubTypes(
JsonSubTypes.Type(value = B::class, name = "test_a"),
JsonSubTypes.Type(value = C::class, name = "test_b")
)
data class Base(
val list:List<A>? = null
)
open class A(
val type: String? = null
)
data class B : A(
val value: String? = null
)
data class C : A(
val values: List<String>? = null
)
the data is reflected in the database as follows
{
"list":[
{
"type": "type a",
"value": "test"
},
{
"type": "type b",
"values": [
"test 1",
"test 2"
]
}
]
}
but when i try to get the data from mongo db it returns it but without the attributes of child classes B and C.
{
"list":[
{
"type": "type a"
},
{
"type": "type b"
}
]
}
I am getting the data using mongoRepository with this annotation.
#Query("{'id' : ?0 }")
fun findById(#Param("id") id: String): Base?
Do you know what could be happening?

How can i return different value from what was in the dropdown in dart?

I am working with dropbox, but what i want to do is retrieve value depending on what the user chooses on the dropbox; for example the users picks "apple" on the dropdownbox what i want to return will be "Vitamin C"
Here is what i have so far:
String myFruits;
List<String> fruits = [
"APPLE",
"ORANGE",
"BANANA",];
DropdownSearch(
onChanged: (dynamic value) {
myFruits = value;
},
mode: Mode.DIALOG,
items: fruits,
),
For now when i print myFruits what it shows is the selected value of the dropbox, what I want is that if pick apple it will return "vitamin c" like that. Thanks :) How can i achieve this?
you can define a Map from fruits and returnedValue like:
Map<String, String> returnedValue = {
"APPLE" : "Vitamin A",
"ORANGE" : "Vitamin C",
"BANANA" : "Vitamin K",
};
and return from this.
all your code like this :
Function(String) returnFunction();
String myFruits;
String myVitamin;
List<String> fruits = [
"APPLE",
"ORANGE",
"BANANA",
];
Map<String, String> returnedValue = {
"APPLE" : "Vitamin A",
"ORANGE" : "Vitamin C",
"BANANA" : "Vitamin K",
};
DropdownSearch(
onChanged: (dynamic value) {
myFruits = value;
myVitamin = returnedValue[value];
returenFunction(myVitamin); // if you want return from this class
},
mode: Mode.DIALOG,
items: fruits,
),

Scala JSON If key matches value return string

I have the JSon response as given below.
If metadata's Organic=true then label='true-Organic', else label='non-Organic'
in the end => return List or Map[modelId,label]
import net.liftweb.json.{DefaultFormats, _}
object test1 extends App {
val json_response =
"""{
"requestId": "91ee60d5f1b45e#316",
"error": null,
"errorMessages": [
],
"entries": [
{
"modelId":"RT001",
"sku": "SKU-ASC001",
"store": "New Jersey",
"ttlInSeconds": 8000,
"metadata": {
"manufactured_date": "2019-01-22T01:25Z",
"organic": "true"
}
},
{
"modelId":"RT002",
"sku": "SKU-ASC002",
"store": "livingstone",
"ttlInSeconds": 8000,
"metadata": {
"manufactured_date": "2019-10-03T01:25Z",
"organic": "false"
}
}
] }"""
tried like this :
val json = parse(json_response)
implicit val formats = DefaultFormats
var map = Map[String, String]()
case class Sales(modelId: String, sku: String, store: String, ttlInSeconds: Int, metadata:
Map[String, String])
case class Response(entries: List[Sales])
val response = json.extract[Response]
After this, not sure how to proceed.
This is a straightforward map operation on the entries field:
response.entries.map{ e =>
e.modelId ->
if (e.metadata.get("organic").contains("true")) {
"true-Organic"
} else {
"non-Organic"
}
}
This will return List[(String, String)], but you can call toMap to turn this into a Map if required.

creating settings of index using elastic4s

I have some class:
class SomeClass(val client: ElasticClient, val config: Config, val configName: String)(implicit val ec: ExecutionContext)
extends ElasticSearchRepositoryWrapper[AnotherClass]{
override def mapping: Option[MappingDefinition] = Some(
properties(
KeywordField("id"),
TextField("name").fielddata(true).analyzer("ngram_analyzer"),
KeywordField("lang"),
BasicField("order", "long"),
...
)
)
I'm creating an index with repository.createIndexIfNotExists() using this mapping.
Now I must create ngram_analyzer in my index settings:
"settings": {
"index": {
"analysis": {
"analyzer": {
"ngram_analyzer": {
"filter": [
"lowercase"
],
"tokenizer": "my_tokenizer"
}
},
"tokenizer": {
"my_tokenizer": {
"token_chars": [
"letter",
"digit"
],
"min_gram": "3",
"type": "ngram",
"max_gram": "3"
}
}
}
}
How can I do that using elastic4s?
OK. A lot of functions of createIndexIfNotExists() were deprecated. So, I used CreateIndexRequest where I put my analyzer:
CreateIndexRequest(repository.indexName, analysis = Option(ngramAnalyzer), mapping = repository.mapping)
.shards(repository.shards)
.replicas(repository.replicas)
And I initialized my analyzer like this:
val ngramAnalyzer = Analysis(
List(CustomAnalyzer(
name = "ngram_analyzer",
tokenizer = "ngram",
charFilters = Nil,
tokenFilters = List("lowercase")
))
)

Need help decoding following json with Circe

I'm trying to parse nested JSON object with Circe library. I would like to map it to flat case class ignoring some of the fields.
import io.circe.generic.auto._
import io.circe.{Decoder, Encoder, HCursor, Json}
val jsonString = """{
"parent" : {
"name" : "title",
"items" : [
{
"foo" : "",
"attrs" : {
"attrA" : "",
"attrB" : ""
}
},
{
"foo" : "",
"attrs" : {
"attrA" : "",
"attrB" : "",
"attrC" : ""
}
}]
}
}"""
// Notice I don't care about "attrC"
case class Item(foo: String, attrA: String, attrB: String)
case class Parent(name: String, items: List[Item])
implicit val testDecoder: Decoder[Item] = Decoder.instance { c =>
val itemsC = c.downField("parent").downField("items")
for {
foo <- itemsC.get[String]("foo")
a <- itemsC.downField("attrs").get[String]("attrA")
b <- itemsC.downField("attrs").get[String]("attrB")
} yield Item(foo, a, b)
}
val decodingResult = parser.decode[Parent](jsonString)
result:
Either[io.circe.Error,Parent] = Left(DecodingFailure(Attempt to decode value on failed cursor, List(DownField(name))))
I find it easier to use the auto-parser, get the data to Scala, and continue from there
import io.circe.generic.auto._
import io.circe.parser._
val sample="""{
"parent" : {
"name" : "title",
"items" : [
{
"foo" : "",
"attrs" : {
"attrA" : "",
"attrB" : ""
}
},
{
"foo" : "",
"attrs" : {
"attrA" : "",
"attrB" : "",
"attrC" : ""
}
}
]
}
}"""
case class Data(parent : Parent)
case class Parent(name: String, items: List[Item])
case class Item(foo: String, attrs : Attrs)
case class Attrs(attrA: String, attrB: String) // you don't need attributes you don't use
val data=decode[Data](sample)