How can I create my data class for my json file? - json

I am a new kotlin programmer and I cant create data class for json file. I always run into a problem. I've worked with simple json files before, but this confused me a bit. How can I convert this json file to data class. By the way, I tried the json to data class, which is an extension of kotlin, then it outputs a data class like this, frankly, this is not a very readable data class, does anyone have a better idea?
my json file
{
"result":"success",
"documentation":"https://www.exchangerate-api.com/docs",
"terms_of_use":"https://www.exchangerate-api.com/terms",
"time_last_update_unix":1669939202,
"time_last_update_utc":"Fri, 02 Dec 2022 00:00:02 +0000",
"time_next_update_unix":1670025602,
"time_next_update_utc":"Sat, 03 Dec 2022 00:00:02 +0000",
"base_code":"USD",
"conversion_rates":{
"USD":1,
"AED":3.6725,
"AFN":88.0236,
"ALL":112.3100,
"AMD":395.3092,
"ANG":1.7900,
"AOA":509.4547,
"ARS":166.9052,
"AUD":1.4696,
"AWG":1.7900,
"AZN":1.6980,
"BAM":1.8638,
"BBD":2.0000,
"BDT":101.4835,
"BGN":1.8647,
"BHD":0.3760,
"BIF":2053.3857,
"BMD":1.0000,
"BND":1.3561,
"BOB":6.9195,
"BRL":5.1984,
"BSD":1.0000,
"BTN":81.0572,
"BWP":13.0619,
"BYN":2.6482,
"BZD":2.0000,
"CAD":1.3433,
"CDF":2054.6915,
"CHF":0.9394,
"CLP":890.3480,
"CNY":7.0548,
"COP":4815.7969,
"CRC":601.6168,
"CUP":24.0000,
"CVE":105.0763,
"CZK":23.2743,
"DJF":177.7210,
"DKK":7.1093,
"DOP":54.3860,
"DZD":138.5331,
"EGP":24.5835,
"ERN":15.0000,
"ETB":53.4963,
"EUR":0.9530,
"FJD":2.1960,
"FKP":0.8183,
"FOK":7.1093,
"GBP":0.8183,
"GEL":2.7103,
"GGP":0.8183,
"GHS":14.1003,
"GIP":0.8183,
"GMD":63.3901,
"GNF":8622.0204,
"GTQ":7.8232,
"GYD":209.1401,
"HKD":7.7836,
"HNL":24.6064,
"HRK":7.1800,
"HTG":140.8970,
"HUF":392.6534,
"IDR":15442.8385,
"ILS":3.4027,
"IMP":0.8183,
"INR":81.0584,
"IQD":1458.8962,
"IRR":42036.3612,
"ISK":142.4758,
"JEP":0.8183,
"JMD":153.8702,
"JOD":0.7090,
"JPY":135.7224,
"KES":123.1351,
"KGS":84.4410,
"KHR":4125.2930,
"KID":1.4694,
"KMF":468.8174,
"KRW":1303.6280,
"KWD":0.2996,
"KYD":0.8333,
"KZT":468.1697,
"LAK":17248.0199,
"LBP":1507.5000,
"LKR":363.4521,
"LRD":153.9744,
"LSL":17.5733,
"LYD":4.8894,
"MAD":10.6209,
"MDL":19.4574,
"MGA":4349.9903,
"MKD":59.4362,
"MMK":2552.4090,
"MNT":3422.5815,
"MOP":8.0171,
"MRU":38.0126,
"MUR":43.4017,
"MVR":15.4048,
"MWK":1032.9387,
"MXN":19.1778,
"MYR":4.4020,
"MZN":63.9513,
"NAD":17.5733,
"NGN":443.8839,
"NIO":36.3799,
"NOK":9.7593,
"NPR":129.6915,
"NZD":1.5722,
"OMR":0.3845,
"PAB":1.0000,
"PEN":3.8347,
"PGK":3.5199,
"PHP":56.1010,
"PKR":224.1295,
"PLN":4.4704,
"PYG":7217.3743,
"QAR":3.6400,
"RON":4.6970,
"RSD":112.1709,
"RUB":61.1764,
"RWF":1114.9049,
"SAR":3.7500,
"SBD":8.1036,
"SCR":13.0656,
"SDG":568.0316,
"SEK":10.3601,
"SGD":1.3561,
"SHP":0.8183,
"SLE":18.6210,
"SLL":18620.9957,
"SOS":568.2695,
"SRD":30.9539,
"SSP":644.4877,
"STN":23.3471,
"SYP":2504.9740,
"SZL":17.5733,
"THB":34.8989,
"TJS":10.1357,
"TMT":3.4988,
"TND":2.9893,
"TOP":2.3706,
"TRY":18.6279,
"TTD":6.7555,
"TVD":1.4694,
"TWD":30.4630,
"TZS":2334.9042,
"UAH":36.4641,
"UGX":3745.5147,
"UYU":39.4017,
"UZS":11238.8195,
"VES":11.2548,
"VND":24496.1101,
"VUV":120.8927,
"WST":2.7081,
"XAF":625.0899,
"XCD":2.7000,
"XDR":0.7578,
"XOF":625.0899,
"XPF":113.7166,
"YER":250.1010,
"ZAR":17.5753,
"ZMW":17.0952,
"ZWL":654.0107
}
}
json to data class kotlin plugin
#Serializable
data class ExchangeDto(
val base_code: String,
val conversion_rates: ConversionRates,
val documentation: String,
val result: String,
val terms_of_use: String,
val time_last_update_unix: Int,
val time_last_update_utc: String,
val time_next_update_unix: Int,
val time_next_update_utc: String
)
#Serializable
data class ConversionRates(
val AED: Double,
val AFN: Double,
val ALL: Double,
val AMD: Double,
val ANG: Double,
val AOA: Double,
val ARS: Double,
val AUD: Double,
val AWG: Double,
val AZN: Double,
val BAM: Double,
val BBD: Double,
val BDT: Double,
val BGN: Double,
val BHD: Double,
val BIF: Double,
val BMD: Double,
val BND: Double,
val BOB: Double,
val BRL: Double,
val BSD: Double,
val BTN: Double,
val BWP: Double,
val BYN: Double,
val BZD: Double,
val CAD: Double,
val CDF: Double,
val CHF: Double,
val CLP: Double,
val CNY: Double,
val COP: Double,
val CRC: Double,
val CUP: Double,
val CVE: Double,
val CZK: Double,
val DJF: Double,
val DKK: Double,
val DOP: Double,
val DZD: Double,
val EGP: Double,
val ERN: Double,
val ETB: Double,
val EUR: Double,
val FJD: Double,
val FKP: Double,
val FOK: Double,
val GBP: Double,
val GEL: Double,
val GGP: Double,
val GHS: Double,
val GIP: Double,
val GMD: Double,
val GNF: Double,
val GTQ: Double,
val GYD: Double,
val HKD: Double,
val HNL: Double,
val HRK: Double,
val HTG: Double,
val HUF: Double,
val IDR: Double,
val ILS: Double,
val IMP: Double,
val INR: Double,
val IQD: Double,
val IRR: Double,
val ISK: Double,
val JEP: Double,
val JMD: Double,
val JOD: Double,
val JPY: Double,
val KES: Double,
val KGS: Double,
val KHR: Double,
val KID: Double,
val KMF: Double,
val KRW: Double,
val KWD: Double,
val KYD: Double,
val KZT: Double,
val LAK: Double,
val LBP: Double,
val LKR: Double,
val LRD: Double,
val LSL: Double,
val LYD: Double,
val MAD: Double,
val MDL: Double,
val MGA: Double,
val MKD: Double,
val MMK: Double,
val MNT: Double,
val MOP: Double,
val MRU: Double,
val MUR: Double,
val MVR: Double,
val MWK: Double,
val MXN: Double,
val MYR: Double,
val MZN: Double,
val NAD: Double,
val NGN: Double,
val NIO: Double,
val NOK: Double,
val NPR: Double,
val NZD: Double,
val OMR: Double,
val PAB: Double,
val PEN: Double,
val PGK: Double,
val PHP: Double,
val PKR: Double,
val PLN: Double,
val PYG: Double,
val QAR: Double,
val RON: Double,
val RSD: Double,
val RUB: Double,
val RWF: Double,
val SAR: Double,
val SBD: Double,
val SCR: Double,
val SDG: Double,
val SEK: Double,
val SGD: Double,
val SHP: Double,
val SLE: Double,
val SLL: Double,
val SOS: Double,
val SRD: Double,
val SSP: Double,
val STN: Double,
val SYP: Double,
val SZL: Double,
val THB: Double,
val TJS: Double,
val TMT: Double,
val TND: Double,
val TOP: Double,
val TRY: Double,
val TTD: Double,
val TVD: Double,
val TWD: Double,
val TZS: Double,
val UAH: Double,
val UGX: Double,
val USD: Int,
val UYU: Double,
val UZS: Double,
val VES: Double,
val VND: Double,
val VUV: Double,
val WST: Double,
val XAF: Double,
val XCD: Double,
val XDR: Double,
val XOF: Double,
val XPF: Double,
val YER: Double,
val ZAR: Double,
val ZMW: Double,
val ZWL: Double
)
I think it's a bad translation when it's like this. How can I improve this or how can I create my own data class

You can do it like this. Instead of having each field for each currencies, you can make coversion_rates as Map , so currency will be the key and value will the currency value. So it will be easier for iterating all currencies, getting value from currency name and so on...
#Serializable
data class ExchangeDto(
val base_code: String,
#TypeConverters(MapTypeConverter::class) //Add annotation
val conversion_rates: Map<String,Double>,
val documentation: String,
val result: String,
val terms_of_use: String,
val time_last_update_unix: Int,
val time_last_update_utc: String,
val time_next_update_unix: Int,
val time_next_update_utc: String
)
Edit:
Type converter for currency map:
object MapTypeConverter {
#TypeConverter
#JvmStatic
fun covertStringToMap(value: String): Map<String, String> {
return Gson().fromJson(value, object : TypeToken<Map<String, String>>() {}.type)
}
#TypeConverter
#JvmStatic
fun mapToString(value: Map<String, String>?): String {
return if(value == null) "" else Gson().toJson(value)
}
}

Related

How to compose functions that return Applicative in point-free style?

This is a follow-up to my previous question:
Suppose I have a few functions that return scalaz.Validaton:
type Status[A] = ValidationNel[String, A]
val isPositive: Int => Status[Int] =
x => if (x > 0) x.success else s"$x not positive".failureNel
val isNegative: Int => Status[Int] =
x => if (x < 0) x.success else s"$x not negative".failureNel
I can write a new function makeX
case class X(x1: Int, // should be positive
x2: Int, // should be positive
x3: Int) // should be negative
val makeX: (Int, Int, Int) => Status[X] = (x1, x2, x3) =>
(isPositive(x1) |#| isPositive(x2) |#| isNegative(x3)) (X.apply _)
My question is: How to write makeX in point-free style
Here's a funky way to make it pointfree:
val makeX: (Int, Int, Int) => Status[X] = isPositive(_) |#| isPositive(_) |#| isNegative(_) apply X

andThen for function of two arguments in Scala

Suppose I have two functions f and g:
val f: (Int, Int) => Int = _ + _
val g: Int => String = _ + ""
Now I would like to compose them with andThen to get a function h
val h: (Int, Int) => String = f andThen g
Unfortunately it doesn't compile :(
scala> val h = (f andThen g)
<console> error: value andThen is not a member of (Int, Int) => Int
val h = (f andThen g)
Why doesn't it compile and how can I compose f and g to get (Int, Int) => String ?
It doesn't compile because andThen is a method of Function1 (a function of one parameter: see the scaladoc).
Your function f has two parameters, so would be an instance of Function2 (see the scaladoc).
To get it to compile, you need to transform f into a function of one parameter, by tupling:
scala> val h = f.tupled andThen g
h: (Int, Int) => String = <function1>
test:
scala> val t = (1,1)
scala> h(t)
res1: String = 2
You can also write the call to h more simply because of auto-tupling, without explicitly creating a tuple (although auto-tupling is a little controversial due to its potential for confusion and loss of type-safety):
scala> h(1,1)
res1: String = 2
Function2 does not have an andThen method.
You can manually compose them, though:
val h: (Int, Int) => String = { (x, y) => g(f(x,y)) }

Functions in scala

I'm having hard time understanding what the following means in scala:
f: Int => Int
Is the a function?
What is the difference between f: Int => Intand def f(Int => Int)?
Thanks
Assuming f: Int => Int is a typo of val f: Int => Int,
and def f(Int => Int) is a typo of def f(i: Int): Int.
val f: Int => Int means that a value f is Function1[Int, Int].
First, A => B equals to =>[A, B].
This is just a shortcut writing, for example:
trait Foo[A, B]
val foo: Int Foo String // = Foo[Int, String]
Second, =>[A, B] equals to Function1[A, B].
This is called "type alias", defined like:
type ~>[A, B] = Foo[A, B]
val foo: Int ~> String // = Foo[Int, String]
def f(i: Int): Int is a method, not a function.
But a value g is Function1[Int, Int] where val g = f _ is defined.
f: Int => Int
means that type of f is Int => Int.
Now what does that mean? It means that f is a function which gets an Int and returns an Int.
You can define such a function with
def f(i: Int): Int = i * 2
or with
def f: Int => Int = i => i * 2
or even with
def f: Int => Int = _ * 2
_ is a placeholder used for designating the argument. In this case the type of the parameter is already defined in Int => Int so compiler knows what is the type of this _.
The following is again equivalent to above definitions:
def f = (i:Int) => i * 2
In all cases type of f is Int => Int.
=>
So what is this arrow?
If you see this arrow in type position (i.e. where a type is needed) it designates a function.
for example in
val func: String => String
But if you see this arrow in an anonymous function it separates the parameters from body of the function. For example in
i => i * 2
To elaborate just slightly on Nader's answer, f: Int => Int will frequently appear in a parameter list for a high order function, so
def myHighOrderFunction(f : Int => Int) : String = {
// ...
"Hi"
}
is a dumb high order function, but shows how you say that myOrderFunction takes as a parameter, f, which is a function that maps an int to an int.
So I might legally call it like this for example:
myHighOrderFunction(_ * 2)
A much more illustrative example comes from Odersky's Programming Scala:
object FileMatcher {
private def filesHere = (new java.io.File(".")).listFiles
private def filesMatching(matcher: String => Boolean) =
for (file <- filesHere if matcher(file.getName))
yield file
def filesEnding(query: String) = filesMatching(_.endsWith(query))
def filesContaining(query: String) = filesMatching(_.contains(query))
def filesRegex(query: String) = filesMatching(_.matches(query))
}
Here filesMatching is a high order function, and we define three other functions that call it passing in different anonymous functions to do different kinds of matching.
Hope that helps.

SML - Creating dictionary that maps keys to values

I need to create a dictionary in sml, but I am having extreme difficulty with an insert function.
type dict = string -> int option
As an example, here is the empty dictionary:
val empty : dict = fn key => NONE
Here is my implementation of an insert function:
fun insert (key,value) d = fn d => fn key => value
But this is of the wrong type, what I need is insert : (string*int) -> dict -> dict.
I've searched everything from lazy functions to implementing dictionaries.
Any help or direction would be greatly appreciateds!
If you are still confused on what I am trying to implement, I drafted up what I should expect to get when calling a simple lookup function
fun lookup k d = d k
- val d = insert ("foo",2) (insert ("bar",3) empty);
val d = fn : string -> int option
- lookup2 "foo" d;
val it = SOME 2 : int option
- lookup2 "bar" d;
val it = SOME 3 : int option
- lookup2 "baz" d;
val it = NONE : int option
You can reason on the signature of the function:
val insert = fn: (string * int) -> dict -> dict
When you supply key, value and a dictionary d, you would like to get back a new dictionary d'. Since dict is string -> int option, d' is a function takes a string and returns an int option.
Suppose you supply a string s to that function. There are two cases which could happen: when s is the same as key you return the associated value, otherwise you return a value by looking up d with key s.
Here is a literal translation:
fun insert (key, value) d = fn s => if s = key then SOME value
else d s

Scala Functional Literals with Implicits

Forgive me if this has already been asked elsewhere. I have a Scala syntax question involving function-values and implicit parameters.
I'm comfortable using implicits with Scala's currying feature. For instance if I had a sum function and wanted to make the second argument an implicit:
scala> def sum(a: Int)(implicit b: Int) = a + b
sum: (a: Int)(implicit b: Int)Int
Is there a way to do this using the function-value syntax? Ignoring the implicit for a moment, I typically write curried function-values like this:
scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>
However, the function signature in the second approach is much different (the currying is being expressed explicitly). Just adding the implicit keyword to b doesn't make much sense and the compiler complains as well:
scala> val sum2 = (a: Int) => (implicit b: Int) => a + b
<console>:1: error: '=>' expected but ')' found.
val sum2 = (a: Int) => (implicit b: Int) => a + b
^
Furthermore partially-applying sum from the very first approach to get a function-value causes problems as well:
scala> val sumFunction = sum _
<console>:14: error: could not find implicit value for parameter b: Int
val sumFunction = sum _
^
This leads me to believe that functions that have implicit parameters must have said parameters determined when the function-value is created, not when the function-value is applied later on. Is this really the case? Can you ever use an implicit parameter with a function-value?
Thanks for the help!
scala> val sum2 = (a: Int) => {implicit b: Int => a + b}
sum2: (Int) => (Int) => Int = <function1>
This will just make b an implicit value for the scope of the function body, so you can call methods that expect an implicit Int.
I don't think you can have implicit arguments for functions since then it is unclear what the function is. Is it Int => Int or () => Int?
The closest I found is:
scala> case class Foo(implicit b: Int) extends (Int => Int) {def apply(a: Int) = a + b}
defined class Foo
scala> implicit val b = 3
b: Int = 3
scala> Foo()
res22: Foo = <function1>
scala> res22(2)
res23: Int = 5
In this snippet
scala> val sum2 = (a: Int) => (b: Int) => a + b
sum: (Int) => (Int) => Int = <function1>
Note that the precise type of sum2 is Function1[Int, Function1[Int, Int]]. It could also be written as
val sum2 = new Function1[Int, Function1[Int, Int]] {
def apply(a: Int) = new Function1[Int, Int] {
def apply(b: Int) = a + b
}
}
Now, if you try to make b implicit, you get this:
scala> val sum2 = new Function1[Int, Function1[Int, Int]] {
| def apply(a: Int) = new Function1[Int, Int] {
| def apply(implicit b: Int) = a + b
| }
| }
<console>:8: error: object creation impossible, since method apply in trait Function1 of type (v1: Int)Int is not defined
def apply(a: Int) = new Function1[Int, Int] {
^
Or, in other words, Function's interfaces do not have implicit parameters, so anything with an implicit parameter is not a Function.
Try overloading the apply method.
scala> val sum = new Function1[Int, Function1[Int, Int]] {
| def apply(a: Int) = (b: Int) => a + b
| def apply(a: Int)(implicit b: Int) = a + b
|}
sum: java.lang.Object with (Int) => (Int) => Int{def apply(a:Int)(implicit b: Int): Int} = <function1>
scala> sum(2)(3)
res0: Int = 5
scala> implicit val b = 10
b: Int = 10
scala> sum(2)
res1: Int = 12