Kotlin Get Value from JSON - kotlin

In the kotlin repl:
>>> import java.io.StringReader
>>> val json = p.parse(StringReader("""{"abc":"123"}""")) as JsonObject
>>> json.string("abc")
error: unresolved reference: string
json.string("abc")
^
>>> json
JsonObject(map={abc=123})
Get error unresolved reference. None of the examples here: https://github.com/cbeust/klaxon work

You need to import the string function as well, since it is an extension function, and it is not imported together with its receiver type Parser by default:
import com.beust.klaxon.string
json.string("abc")

Related

Can Kotlin extension functions be called without an import declaration?

Is it possible to call an extension function from another package without importing it?
Given an extension function:
package ext
fun Int.plusOne() = this + 1
Is there any way to call this function without importing the function first?
I can call non-extension functions without an import (ignore that the function does not need to be imported, just note that the syntax is valid):
val el: List<Int> = kotlin.emptyList()
I can instantiate classes without an import:
val str = java.lang.String("yo.")
But I have not yet found the equivalent for extensions (I know some examples are silly):
val i = 42
// All those are not valid syntax...
i.ext.plusOne()
ext.plusOne(i)
i.(ext.plusOne)()
i.(ext.plusOne())
ext.i.plusOne()
val pO = ext.plusOne
i.pO()
Bonus: Same question, but for extension properties.
Edit: To add to the list of invalid examples, even at places where the extension receiver is implicit, FQDNs are not allowed:
// Good:
import ext.plusOne
val four = with(3) { plusOne() }
// Unresolved reference:
val four = with(3) { ext.plusOne() }
No, according to the spec. A call can only be these forms:
A fully-qualified call without receiver: package.foo();
A call with an explicit receiver: a.foo();
An infix function call: a foo b;
An overloaded operator call: a + b;
A call without an explicit receiver: foo().
Notice that the "fully-qualified call" form, which is the only form that allows the use of package names, explicitly says "without receiver". However, your plusOne requires an Int as a receiver. In fact, by definition, all extensions functions/properties require a receiver by definition.
I also tried looking at callable references, in hopes of making a callable reference to plusOne using a fully qualified name, and then calling that callable reference. However, it turns out the syntax for those is even stricter.
Therefore, this cannot be done without modifying the ext package in some way, like adding a "wrapper" function.
After all, there is really no need for such a feature. Importing is not that hard - the IDE does it all for you these days. If you need to import two things with the same name, use an import alias:
import package1.extFunc as pack1ExtFunc
import package2.extFunc as pack2ExtFunc

Kotlin compile error "unresolved reference" only when compiling from command line

I have the Kotlin code:
import com.google.gson.Gson
import java.io.File
class System {
/*
Save current game state to file
*/
internal fun saveGameState(game: Game) {
val gameState = game.getGameState()
val gson = Gson()
val jsonString = gson.toJson(gameState)
val pathname = FILENAME_SAVED_GAME
File(pathname).writeText(jsonString)
}
private fun loadGameState(): Game {
val jsonString = File(FILENAME_SAVED_GAME).readText(Charsets.UTF_8)
val gson = Gson()
val gameState: GameState = gson.fromJson(jsonString, GameState::class.java)
File(FILENAME_SAVED_GAME).delete()
return Game(gameState)
}
...
}
When I run it from within IntelliJIDEA, it compiles and runs fine, including using this class to save state and restore state.
When I compile it from the command line, I use this command:
kotlinc *.kt -include-runtime -d GizmosK.jar
and I this error message:
System.kt:1:12: error: unresolved reference: google
import com.google.gson.Gson
^
System.kt:11:20: error: unresolved reference: Gson
val gson = Gson()
^
System.kt:19:20: error: unresolved reference: Gson
val gson = Gson()
^
I've successfully used this command many times before, but possibly not since adding this System class, which is the only one that imports anything from outside my project.
I've searched, and found this question which appears very similar to my problem, but I have a few concerns.
First, I don't know if this solution applies to my situation since my code is pure Kotlin and not Android.
Second, I don't know how to generalize their solution and make it apply to my situation. Like, I know I probably have to replace something with google.gson or com.google.gson or com.google.gson.Gson in there somewhere, but I don't know where, since there are three things there that look like package names. Do I need all three? I also don't know if expressions like package_name are literal strings I should enter verbatim or if I should replace those words with the actual package name.
Third, I've never had to specify flovar/flavor nor resource_package before in a command line, and I don't want to introduce new variables, if at all possible.
BTW, I'm compiling from the command line to generate a .jar file to distribute so anyone can run it from the command line without sharing my code or requiring they install IntelliJ IDEA.

"pydantic\validators.py" : no validator found for <class 'pandas.core.frame.DataFrame'>

Below DataFrame of pandas is not validated by pydantic. How to handle this?
from pydantic.dataclasses import dataclass
#dataclass
class DataFrames:
dataframe1: pd.DataFrame = None
dataframe2: pd.DataFrame = None
This throws the following error:
File "pydantic\validators.py", line 715, in find_validators
RuntimeError: no validator found for <class 'pandas.core.frame.DataFrame'>, see `arbitrary_types_allowed` in Config
Personally, I'd mistyped the type annotation
class Foo(BaseModel):
bar = Optional[NonNegativeInt]
Rather than;
class Foo(BaseModel):
bar: Optional[NonNegativeInt]
Silly one ik, but double check that :)
According to the Pydantic Docs, you can solve your problems in several ways.
The simplest one is simply to allow arbitrary types in the model config, but this is functionality packaged with the BaseModel : quoting the docs again :
Keep in mind that pydantic.dataclasses.dataclass is a drop-in replacement for dataclasses.dataclass with validation, not a replacement for pydantic.BaseModel
With that in mind, the following code runs fine :
import pandas as pd
from pydantic import BaseModel
class DataFrames(BaseModel):
dataframe1: pd.DataFrame = None
dataframe2: pd.DataFrame = None
class Config:
arbitrary_types_allowed = True
If you came here with general problem no validator found for <class 'XYZ'> you should check missed BaseModel inheritance:
from pydantic import BaseModel
class MyCustomType: # We forgot inheritance here, should be MyCustomType(BaseModel)
id: int
text: str
class MyCustomClass2(BaseModel):
data: List[MyCustomType]

How to map a List to a Set while applying a method(Java to Kotlin code conversion)?

I have this code snippet in Java (this is an MCVE; actual code is more complex but has exact same issue):
enum StatusEnum { A, B, C; }
[...]
final static Set<String> names = Arrays.asList(StatusEnum.values())
.stream().map(StatusEnum::name).collect(Collectors.toSet());
IntelliJ gave me the following automated conversion to Kotlin:
internal val names = Arrays.asList(*StatusEnum.values())
.stream().map<String>(Function<StatusEnum, String> { it.name })
.collect<Set<String>, Any>(Collectors.toSet())
This unfortunately has compile errors:
Interface Function does not have constructors
Type inference failed. Expected type mismatch: inferred type is Collector!>! but Collector!>! was expected
Unresolved reference: it
This is my very first attempt at converting some code to Kotlin. I have reviewed the Functions and Lambdas section of the documentation. Still not clear what's going on here or how to fix it.
Use Kotlin methods instead of Java streams:
val names = StatusEnum.values()
.map { it.name }
.toSet()

Using applyOptional in Monocle

I'm trying to figure out how to use applyOptional. I've got this:
import monocle.function.all.index
import monocle.macros.{GenLens, Lenses}
import monocle.std.map._
import monocle.syntax.ApplyOptionalOps._
import monocle.function.Index._
val map: Map[Int, String] = Map.empty
val lens = map applyOptional index(4)
But the compiler tells me "Cannot resolve symbol applyOptional." I imported ApplyOptionalOps._ just to confirm that I had the right imports.
ApplyOptionalOps is the case class with the source object as the parameter, so by importing its companion object one can't access its functions. One should import monocle.syntax.apply._ instead, which extends ApplySyntax trait containing implicit conversion from generic source object to ApplyOptionalOps as well as some other operation wrappers. In fact, for just this example it the following imports is sufficient:
import monocle.syntax.apply._
import monocle.function.Index._
val map: Map[Int, String] = Map.empty
val lens = map applyOptional index(4)