@@ -26,7 +26,6 @@ import org.jetbrains.kotlinx.dataframe.api.isColumnGroup
26
26
import org.jetbrains.kotlinx.dataframe.api.isFrameColumn
27
27
import org.jetbrains.kotlinx.dataframe.api.isSubtypeOf
28
28
import org.jetbrains.kotlinx.dataframe.api.map
29
- import org.jetbrains.kotlinx.dataframe.api.parser
30
29
import org.jetbrains.kotlinx.dataframe.api.to
31
30
import org.jetbrains.kotlinx.dataframe.columns.TypeSuggestion
32
31
import org.jetbrains.kotlinx.dataframe.columns.size
@@ -214,7 +213,7 @@ internal object Parsers : GlobalParserOptions {
214
213
.parseOrNull(this )
215
214
?.toInstantUsingOffset()
216
215
}
217
- // fallback on the java instant to catch things like "2022-01-23T04:29:60", a.k.a. leap seconds
216
+ // fallback on the java instant to catch things like "2022-01-23T04:29:60", a.k.a. leap seconds
218
217
? : toJavaInstantOrNull()?.toKotlinInstant()
219
218
220
219
private fun String.toJavaInstantOrNull (): JavaInstant ? =
@@ -338,6 +337,94 @@ internal object Parsers : GlobalParserOptions {
338
337
parser
339
338
}
340
339
340
+ // TODO rewrite using parser service later https://github.com/Kotlin/dataframe/issues/962
341
+ // null when dataframe-json is not present
342
+ private val readJsonStrAnyFrame: ((text: String ) -> AnyFrame )? by lazy {
343
+ try {
344
+ val klass = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JsonKt" )
345
+ val typeClashTactic = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JSON\$ TypeClashTactic" )
346
+ val readJsonStr = klass.getMethod(
347
+ " readJsonStr" ,
348
+ // this =
349
+ DataFrame .Companion ::class .java,
350
+ // text =
351
+ String ::class .java,
352
+ // header =
353
+ List ::class .java,
354
+ // keyValuePaths =
355
+ List ::class .java,
356
+ // typeClashTactic =
357
+ typeClashTactic,
358
+ // unifyNumbers =
359
+ Boolean ::class .java,
360
+ )
361
+
362
+ return @lazy { text: String ->
363
+ readJsonStr.invoke(
364
+ null ,
365
+ // this =
366
+ DataFrame .Companion ,
367
+ // text =
368
+ text,
369
+ // header =
370
+ emptyList<Any >(),
371
+ // keyValuePaths =
372
+ emptyList<Any >(),
373
+ // typeClashTactic =
374
+ typeClashTactic.enumConstants[0 ],
375
+ // unifyNumbers =
376
+ true ,
377
+ ) as AnyFrame
378
+ }
379
+ } catch (_: ClassNotFoundException ) {
380
+ return @lazy null
381
+ }
382
+ }
383
+
384
+ // TODO rewrite using parser service later https://github.com/Kotlin/dataframe/issues/962
385
+ // null when dataframe-json is not present
386
+ private val readJsonStrAnyRow: ((text: String ) -> AnyRow )? by lazy {
387
+ try {
388
+ val klass = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JsonKt" )
389
+ val typeClashTactic = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JSON\$ TypeClashTactic" )
390
+ val readJsonStr = klass.getMethod(
391
+ " readJsonStr" ,
392
+ // this =
393
+ DataRow .Companion ::class .java,
394
+ // text =
395
+ String ::class .java,
396
+ // header =
397
+ List ::class .java,
398
+ // keyValuePaths =
399
+ List ::class .java,
400
+ // typeClashTactic =
401
+ typeClashTactic,
402
+ // unifyNumbers =
403
+ Boolean ::class .java,
404
+ )
405
+
406
+ return @lazy { text: String ->
407
+ readJsonStr.invoke(
408
+ null ,
409
+ // this =
410
+ DataRow .Companion ,
411
+ // text =
412
+ text,
413
+ // header =
414
+ emptyList<Any >(),
415
+ // keyValuePaths =
416
+ emptyList<Any >(),
417
+ // typeClashTactic =
418
+ typeClashTactic.enumConstants[0 ],
419
+ // unifyNumbers =
420
+ true ,
421
+ ) as AnyRow
422
+ }
423
+ } catch (_: ClassNotFoundException ) {
424
+ return @lazy null
425
+ }
426
+ }
427
+
341
428
internal val parsersOrder = listOf (
342
429
// Int
343
430
stringParser<Int > { it.toIntOrNull() },
@@ -407,70 +494,33 @@ internal object Parsers : GlobalParserOptions {
407
494
stringParser<BigInteger > { it.toBigIntegerOrNull() },
408
495
// BigDecimal
409
496
stringParser<BigDecimal > { it.toBigDecimalOrNull() },
410
-
411
- // JSON array as DataFrame<*> TODO
497
+ // JSON array as DataFrame<*>
412
498
stringParser<AnyFrame >(catch = true ) {
413
499
val trimmed = it.trim()
414
500
if (trimmed.startsWith(" [" ) && trimmed.endsWith(" ]" )) {
415
- try {
416
- val klass = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JsonKt" )
417
- val typeClashTactic = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JSON\$ TypeClashTactic" )
418
- val readJsonStr = klass.getMethod(
419
- " readJsonStr" ,
420
- /* this = */ DataFrame .Companion ::class .java,
421
- /* text = */ String ::class .java,
422
- /* header = */ List ::class .java,
423
- /* keyValuePaths = */ List ::class .java,
424
- /* typeClashTactic = */ typeClashTactic,
425
- /* unifyNumbers = */ Boolean ::class .java,
426
- )
427
-
428
- readJsonStr.invoke(
429
- null ,
430
- /* this = */ DataFrame .Companion ,
431
- /* text = */ trimmed,
432
- /* header = */ emptyList<Any >(),
433
- /* keyValuePaths = */ emptyList<Any >(),
434
- /* typeClashTactic = */ typeClashTactic.enumConstants[0 ],
435
- /* unifyNumbers = */ true ,
436
- ) as AnyFrame
437
- } catch (_: ClassNotFoundException ) {
438
- logger.warn { " parse() encountered a string that looks like a JSON array, but the dataframe-json dependency was not detected. Skipping for now." }
501
+ if (readJsonStrAnyFrame == null ) {
502
+ logger.warn {
503
+ " parse() encountered a string that looks like a JSON array, but the dataframe-json dependency was not detected. Skipping for now."
504
+ }
439
505
null
506
+ } else {
507
+ readJsonStrAnyFrame!! (trimmed)
440
508
}
441
509
} else {
442
510
null
443
511
}
444
512
},
445
- // JSON object as DataRow<*> TODO
513
+ // JSON object as DataRow<*>
446
514
stringParser<AnyRow >(catch = true ) {
447
515
val trimmed = it.trim()
448
516
if (trimmed.startsWith(" {" ) && trimmed.endsWith(" }" )) {
449
- try {
450
- val klass = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JsonKt" )
451
- val typeClashTactic = Class .forName(" org.jetbrains.kotlinx.dataframe.io.JSON\$ TypeClashTactic" )
452
- val readJsonStr = klass.getMethod(
453
- " readJsonStr" ,
454
- /* this = */ DataRow .Companion ::class .java,
455
- /* text = */ String ::class .java,
456
- /* header = */ List ::class .java,
457
- /* keyValuePaths = */ List ::class .java,
458
- /* typeClashTactic = */ typeClashTactic,
459
- /* unifyNumbers = */ Boolean ::class .java,
460
- )
461
-
462
- readJsonStr.invoke(
463
- null ,
464
- /* this = */ DataRow .Companion ,
465
- /* text = */ trimmed,
466
- /* header = */ emptyList<Any >(),
467
- /* keyValuePaths = */ emptyList<Any >(),
468
- /* typeClashTactic = */ typeClashTactic.enumConstants[0 ],
469
- /* unifyNumbers = */ true ,
470
- ) as AnyRow
471
- } catch (_: ClassNotFoundException ) {
472
- logger.warn { " parse() encountered a string that looks like a JSON object, but the dataframe-json dependency was not detected. Skipping for now." }
517
+ if (readJsonStrAnyRow == null ) {
518
+ logger.warn {
519
+ " parse() encountered a string that looks like a JSON object, but the dataframe-json dependency was not detected. Skipping for now."
520
+ }
473
521
null
522
+ } else {
523
+ readJsonStrAnyRow!! (trimmed)
474
524
}
475
525
} else {
476
526
null
0 commit comments