io.circe encoder for java.lang.Object in scala - scala

How to encode java.lang.Object using io.circe
Basically I am trying encode a Map
Map(
"key" -> Option[Json].map(_.asObject).getOrElse(Map.empty) // `object[a -> "x",b -> "y",c -> "z"]`
)
For e.g. I want to convert object[a -> "x",b -> "y",c -> "z"] to {"a":"x", "b":"y","c": "z"}

Related

How does typecasting/polymorphism work with this nested, closure type in Swift?

I know that (Int) -> Void can't be typecasted to (Any) -> Void:
let intHandler: (Int) -> Void = { i in
print(i)
}
var anyHandler: (Any) -> Void = intHandler <<<< ERROR
This gives:
error: cannot convert value of type '(Int) -> Void' to specified type
'(Any) -> Void'
Question: But I don't know why this work?
let intResolver: ((Int) -> Void) -> Void = { f in
f(5)
}
let stringResolver: ((String) -> Void) -> Void = { f in
f("wth")
}
var anyResolver: ((Any) -> Void) -> Void = intResolver
I messed around with the return type and it still works...:
let intResolver: ((Int) -> Void) -> String = { f in
f(5)
return "I want to return some string here."
}
let stringResolver: ((String) -> Void) -> Void = { f in
f("wth")
}
var anyResolver: ((Any) -> Void) -> Any = intResolver (or stringResolver)
Sorry if this is asked before. I couldn't find this kind of question yet, maybe I don't know the keyword here.
Please enlighten me!
If you want to try: https://iswift.org/playground?wZgwi3&v=3
It's all about variance and Swift closures.
Swift is covariant in respect to closure return type, and contra-variant in respect to its arguments. This makes closures having the same return type or a more specific one, and same arguments or less specific, to be compatible.
Thus (Arg1) -> Res1 can be assigned to (Arg2) -> Res2 if Res1: Res2 and Arg2: Arg1.
To express this, let's tweak a little bit the first closure:
import Foundation
let nsErrorHandler: (CustomStringConvertible) -> NSError = { _ in
return NSError(domain: "", code: 0, userInfo: nil)
}
var anyHandler: (Int) -> Error = nsErrorHandler
The above code works because Int conforms to CustomStringConvertible, while NSError conforms to Error. Any would've also work instead of Error as it's even more generic.
Now that we established that, let's see what happens in your two blocks of code.
The first block tries to assign a more specific argument closure to a less specific one, and this doesn't follow the variance rules, thus it doesn't compile.
How about the second block of code? We are in a similar scenario as in the first block: closures with one argument.
we know that String, or Void, is more specific that Any, so we can use it as return value
(Int) -> Void is more specific than (Any) -> Void (closure variance rules), so we can use it as argument
The closure variance is respected, thus intResolver and stringResolver are a compatible match for anyResolver. This sounds a little bit counter-intuitive, but still the compile rules are followed, and this allows the assignment.
Things complicate however if we want to use closures as generic arguments, the variance rules no longer apply, and this due to the fact that Swift generics (with few exceptions) are invariant in respect to their type: MyGenericType<B> can't be assigned to MyGenericType<A> even if B: A. The exceptions are standard library structs, like Optional and Array.
First, let's consider exactly why your first example is illegal:
let intHandler: (Int) -> Void = { i in
print(i)
}
var anyHandler: (Any) -> Void = intHandler
// error: Cannot convert value of type '(Int) -> Void' to specified type '(Any) -> Void'
An (Any) -> Void is a function that can deal with any input; an (Int) -> Void is a function that can only deal with Int input. Therefore it follows that we cannot treat an Int-taking function as a function that can deal with anything, because it can't. What if we called anyHandler with a String?
What about the other way around? This is legal:
let anyHandler: (Any) -> Void = { i in
print(i)
}
var intHandler: (Int) -> Void = anyHandler
Why? Because we can treat a function that deals with anything as a function that can deal with Int, because if it can deal with anything, by definition it must be able to deal with Int.
So we've established that we can treat an (Any) -> Void as an (Int) -> Void. Let's look at your second example:
let intResolver: ((Int) -> Void) -> Void = { f in
f(5)
}
var anyResolver: ((Any) -> Void) -> Void = intResolver
Why can we treat a ((Int) -> Void) -> Void as an ((Any) -> Void) -> Void? In other words, why when calling anyResolver can we forward an (Any) -> Void argument onto an (Int) -> Void parameter? Well, as we've already found out, we can treat an (Any) -> Void as an (Int) -> Void, thus it's legal.
The same logic applies for your example with ((String) -> Void) -> Void:
let stringResolver: ((String) -> Void) -> Void = { f in
f("wth")
}
var anyResolver: ((Any) -> Void) -> Void = stringResolver
When calling anyResolver, we can pass an (Any) -> Void to it, which then gets passed onto stringResolver which takes a (String) -> Void. And a function that can deal with anything is also a function that deals with strings, thus it's legal.
Playing about with the return types works:
let intResolver: ((Int) -> Void) -> String = { f in
f(5)
return "I want to return some string here."
}
var anyResolver: ((Any) -> Void) -> Any = intResolver
Because intResolver says it returns a String, and anyResolver says it returns Any; well a string is Any, so it's legal.

Extracting Map values from a List of Maps List[Map[String,Any]]?

how would you go about pattern matching to extract values from Maps contained in a List ?
So my data is of type List[Map[String,Any]] and looks like :
List(Map(sequence -> 192, id -> 8697413670252052, type -> List(AimLowEvent, DiscreteEvent), time -> 527638582195))
List(Map(duration -> 143858743, id -> 8702168014834892, sequence -> 195, sessionId -> 8697344444103393, time -> 527780267698, type -> List(SessionCanceled, SessionEnded)), Map(trackingInfo -> Map(trackId -> 14170286, location -> Browse, listId -> cd7c2c7a-00f6-4035-867f-d1dd7d89972d_6625365X3XX1505943605585, videoId -> 80000778, rank -> 0, row -> 0, requestId -> ac12f4e1-5644-46af-87d1-ec3b92ce4896-4071171), id -> 8697344444103393, sequence -> 89, time -> 527636408955, type -> List(Play, Action, Session)), 1)
List(Map(duration -> 142862569, id -> 8702168403395215, sequence -> 201, sessionId -> 8697374208897843, time -> 527780267698, type -> List(SessionCanceled, SessionEnded)), Map(trackingInfo -> Map(trackId -> 14170286, location -> Browse, listId -> cd7c2c7a-00f6-4035-867f-d1dd7d89972d_6625365X3XX1505943605585, videoId -> 80000778, rank -> 0, row -> 0, requestId -> ac12f4e1-5644-46af-87d1-ec3b92ce4896-4071171), id -> 8697374208897843, sequence -> 136, time -> 527637405129, type -> List(Play, Action, Session)), 1)
Firstly I would only like to keep records that contain the Map(trackingInfo -> .. as the fields that are important to me are in those records, e.g trackId. However in those same records I need the outer fields also such as sequence
I've tired to flatten the list into a Map by, so I can match on the maps:
myList.flatten.toMap
However it returns a java.lang.ClassCastException: scala.collection.immutable.Map$Map4 cannot be cast to scala.Tuple2 error.
Any help is appreciated
For what you want to achieve, I believe a filter will do:
// taken from your example and simplified
val list =
List(
Map("duration" -> 142862569L, "id" -> 8702168403395215L, "sequence" -> 201, "sessionId" -> 8697374208897843L, "time" -> 527780267698L, "type" -> List("SessionCanceled", "SessionEnded")),
Map("trackingInfo" -> Map("trackId" -> 14170286L, "location" -> "Browse", "listId" -> "cd7c2c7a-00f6-4035-867f-d1dd7d89972d_6625365X3XX1505943605585", "videoId" -> "80000778", "rank" -> 0, "row" -> 0, "requestId" -> "ac12f4e1-5644-46af-87d1-ec3b92ce4896-4071171"), "id" -> 8697374208897843L, "sequence" -> 136, "time" -> 527637405129L, "type" -> List("Play", "Action", "Session")))
val onlyWithTrackingInfo =
list.filter(_.contains("trackingInfo"))
Printing onlyWithTrackingInfo would output the following (prettified):
List(
Map(
trackingInfo -> Map(trackId -> 14170286, location -> Browse, listId -> cd7c2c7a-00f6-4035-867f-d1dd7d89972d_6625365X3XX1505943605585, videoId -> 80000778, rank -> 0, row -> 0, requestId -> ac12f4e1-5644-46af-87d1-ec3b92ce4896-4071171),
id -> 8697374208897843,
sequence -> 136,
time -> 527637405129,
type -> List(Play, Action, Session)
)
)
One approach would be to collect any Map that consists of the wanted key:
def extract(list: List[Map[String, Any]], key: String) = list.collect{
case m if m.get(key) != None => m
}
val list1: List[Map[String, Any]] = List(
Map("sequence" -> 192, "id" -> 8697413670252052L, "type" -> List("AimLowEvent", "DiscreteEvent"), "time" -> 527638582195L)
)
val list2: List[Map[String, Any]] = List(
Map("duration" -> 143858743, "id" -> 8702168014834892L, "sequence" -> 195, "sessionId" -> 8697344444103393L, "time" -> 527780267698L, "type" -> List("SessionCanceled", "SessionEnded")),
Map("trackingInfo" -> Map("trackId" -> 14170286, "location" -> "Browse", "listId" -> "cd7c2c7a-00f6-4035-867f-d1dd7d89972d_6625365X3XX1505943605585", "videoId" -> 80000778, "rank" -> 0, "row" -> 0, "requestId" -> "ac12f4e1-5644-46af-87d1-ec3b92ce4896-4071171"), "id" -> 8697344444103393L, "sequence" -> 89, "time" -> 527636408955L, "type" -> List("Play", "Action", "Session"))
)
extract(list1, "trackingInfo")
// res1: List[Map[String,Any]] = List()
extract(list2, "trackingInfo")
// res2: List[Map[String,Any]] = List(
// Map(trackingInfo -> Map(trackId -> 14170286, location -> Browse, listId -> cd7c2c7a-00f6-4035-867f-d1dd7d89972d_6625365X3XX1505943605585, videoId -> 80000778, rank -> 0, row -> 0, requestId -> ac12f4e1-5644-46af-87d1-ec3b92ce4896-4071171), id -> 8697344444103393, sequence -> 89, time -> 527636408955, type -> List(Play, Action, Session))
// )

How Do I fix the Swift Sort function error?

I have a Swift1 book, but I have Xcode 7. So I am coding Swift2 based on a Swift1 book. I'm currently learning Swift closure, but the following code produces an error.
import Cocoa
let names = ["Chris","Alex","Ewa","Barry","Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
print("Unsort names: \(names)")
var reversed = sort(names, backwards)
print("sort names: \(reversed)")
This is the error:
Playground execution failed: /var/folders/kt/t3wp7ckx3h1c33tfm44r4zgr0000gn/T/./lldb/1968/playground150.swift:11:16:
error: cannot invoke 'sort' with an argument list of type '([String], (String, s2: String) -> Bool)'
var reversed = sort(names, backwards)
^
/var/folders/kt/t3wp7ckx3h1c33tfm44r4zgr0000gn/T/./lldb/1968/playground150.swift:11:16:
note: overloads for 'sort' exist with these partially matching parameter lists: (inout C, (C.Generator.Element, C.Generator.Element) -> Bool), (inout [T], (T, T) -> Bool), (inout ContiguousArray<T>, (T, T) -> Bool)
var reversed = sort(names, backwards)
You have to apply sort function to an array object
var reversed = names.sort(backwards)
Below is the screenshot of my playground

Using Array.map instead of array.map

Here is what I can do in Swift:
extension Int {
func square() -> Int { return self * self }
}
And then call it like this: 3.square(), that gives me 9. Also, i can do it like so: Int.square(3), and it will give me () -> (Int). So, Int.square(3)() gives 9.
But if I write let array = [1, 2, 3]; Array.map(array) it gives error Cannot convert value of type 'Array<Int>' to expected argument of type '[_]'
Question is, how I can use Array.map in that way?
EDIT
Ok, I'll try to explain my problem in details. Now, I have function like this:
func map<T, U>(f: T -> U) -> [T] -> [U] {
return { ts in
ts.map(f)
}
}
It works, but only on arrays. There are many types that have map function, and it not very nice to declare global function like that for every type. So, lets say there is type C that have map function C<T> -> (T -> U) -> C<U>
Also, lets say I have function f, that transform A -> B -> C into B -> A -> C.
So, it looks like I can do something like this:
let array = [1, 2, 3]
let square: Int -> Int = {$0 * $0}
map(square)(array) // [1, 4, 9], works fine
f(Array.map)(square)(array) // Error
Question is not about code readability but about how Swift's type system works.
Array.map function is defined as:
public func map<T>(self: [Self.Generator.Element]) -> (#noescape Self.Generator.Element throws -> T) rethrows -> [T]
The problem here is that the compiler cannot infer the return type of the transform function or T. So you have to define it the two following ways:
// variable declaration
let mapping: (Int -> Int) throws -> [Int] = Array.map(array)
// or (especially useful for further function calls)
aFunction(Array.map(array) as (Int -> Int) throws -> [Int])
You can also see that the map function is marked as rethrows which gets "translated" to throws if you use the function. (It looks like a bug but closures don't have rethrows which could be the reason for this behavior).
So the function f could look like this in order to use it with Array.map:
// where
// A is the array
// B is the function
// C the type of the returned array
func f<A, B, C>(f2: A -> (B throws -> C)) -> B -> (A throws -> C) {
return { b in
{ a in
try f2(a)(b)
}
}
}
// or with a forced try! so you don't have to use try
func f<A, B, C>(f2: A -> (B throws -> C)) -> B -> A -> C {
return { b in
{ a in
try! f2(a)(b)
}
}
}
// call f (use try if you use the first implementation)
let square: Int -> Int = {$0 * $0}
f(Array.map)(square)
In the example with square the compiler can infer the type of the expression. In other words:
let f = Int.square(3)
is the same as
let f:() -> Int = Int.square(3)
However, map is a generic function that is parameterized on the closure return type:
public func map<T>(#noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
Consequently, this generates an error because the compiler doesn't know what T is:
let f = Array<Int>.map([1, 2, 3])
However, you can explicitly tell it what T is like this:
let f: ((Int) throws -> Int) throws -> [Int] = Array.map([1, 2, 3])
try! f({$0 * $0})
I think that answers your first question about square and map. I don't completely understand the rest of your question about converting A -> B -> C to B -> A -> C. Maybe you can provide more info on what f would look like.

How can I have a empty number on play forms?

I have a form in my application that will insert information into the database, but its optional data, it can be nullable. I have this mapping:
case class TransactionFormData(id:Long, transID:Long, operatorID:Long, cardID:Long, stationID:Long, startTime:String, endTime:String, lineNumber:Int, cardNumber:Long, transNumber:Long, ticketNumber:Int, amountEntered:Int, amountMeasured:Int, leaseID_dpID:Int, customerID:Int)
val transForm = Form(
mapping(
"id" -> longNumber,
"transID" -> longNumber,
"operatorID" -> longNumber(min = 0),
"cardID" -> longNumber,
"stationID" -> longNumber,
"startTime" -> nonEmptyText,
"endTime" -> nonEmptyText,
"lineNumber" -> number(min = 0),
"cardNumber" -> longNumber(min = 0),
"transNumber" -> longNumber(min = 0),
"ticketNumber" -> OptionalMapping(number),
"amountEntered" -> number,
"amountMeasured" -> number,
"leaseID_dpID" -> number,
"customerID" -> number
)(TransactionFormData.apply)(TransactionFormData.unapply)
)
from ticketNumber on down, the values can be kept empty, but when I try putting nothing in, the form helper returns an error and requires input, how can I stop this?
Use the optional(number) constraint:
"ticketNumber" -> optional(number),
"amountEntered" -> optional(number),
"amountMeasured" -> optional(number),
"leaseID_dpID" -> optional(number),
"customerID" -> optional(number)
Just as number maps to Int, optional(number) maps to Some[Int]. The constraint allows the field to pass validation if no value is submitted in the form, assigning the field the value None. I appreciate however that this will then require you to change the signature of your case class constructor:
case class TransactionFormData(..., ticketNumber:Option[Int], ...)