Skip to content

Commit ae91f24

Browse files
committed
Fix serialization for DataColumn<List?> and for unnamed columns
1 parent def9135 commit ae91f24

File tree

2 files changed

+27
-3
lines changed
  • core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io
  • tests/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io

2 files changed

+27
-3
lines changed

core/src/main/kotlin/org/jetbrains/kotlinx/dataframe/io/json.kt

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ internal fun KlaxonJson.encodeRow(frame: ColumnsContainer<*>, index: Int): JsonO
211211
col is ColumnGroup<*> -> encodeRow(col, index)
212212
col is FrameColumn<*> -> col[index]?.let { encodeFrame(it) }
213213
col.isList() -> {
214-
array(col[index] as List<*>)
214+
col[index]?.let { array(it as List<*>) } ?: array()
215215
}
216216
col.typeClass in valueTypes -> {
217217
val v = col[index]
@@ -229,8 +229,13 @@ internal fun KlaxonJson.encodeRow(frame: ColumnsContainer<*>, index: Int): JsonO
229229
internal fun KlaxonJson.encodeFrame(frame: AnyFrame): JsonArray<*> {
230230
val allColumns = frame.columns()
231231

232+
// if there is only 1 column, then `isValidValueColumn` always true.
233+
// But at the same time, we shouldn't treat dataFrameOf("value")(1,2,3) like unnamed column
234+
// because it was created by user.
235+
val isPossibleToFindUnnamedColumns = allColumns.size != 1
232236
val valueColumn = allColumns.filter { it.name.startsWith(valueColumnName) }
233-
.maxByOrNull { it.name }?.let { valueCol ->
237+
.takeIf { isPossibleToFindUnnamedColumns }
238+
?.maxByOrNull { it.name }?.let { valueCol ->
234239
if (valueCol.kind() != ColumnKind.Value) null
235240
else {
236241
// check that value in this column is not null only when other values are null
@@ -248,7 +253,8 @@ internal fun KlaxonJson.encodeFrame(frame: AnyFrame): JsonArray<*> {
248253
}
249254

250255
val arrayColumn = frame.columns().filter { it.name.startsWith(arrayColumnName) }
251-
.maxByOrNull { it.name }?.let { arrayCol ->
256+
.takeIf { isPossibleToFindUnnamedColumns }
257+
?.maxByOrNull { it.name }?.let { arrayCol ->
252258
if (arrayCol.kind() == ColumnKind.Group) null
253259
else {
254260
// check that value in this column is not null only when other values are null

tests/src/test/kotlin/org/jetbrains/kotlinx/dataframe/io/json.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.jetbrains.kotlinx.dataframe.io
22

33
import io.kotest.matchers.shouldBe
4+
import io.kotest.matchers.string.shouldContain
45
import org.jetbrains.kotlinx.dataframe.DataFrame
56
import org.jetbrains.kotlinx.dataframe.api.convert
67
import org.jetbrains.kotlinx.dataframe.api.dataFrameOf
@@ -139,6 +140,23 @@ class JsonTests {
139140
DataFrame.readJsonStr(df.toJson()) shouldBe df
140141
}
141142

143+
@Test
144+
fun `list serialization with nulls`() {
145+
val df = dataFrameOf("a")(listOf(1, 2, 3), null)
146+
val text = df.toJson()
147+
val df1 = DataFrame.readJsonStr(text)
148+
df1["a"][1] shouldBe emptyList<Int>()
149+
}
150+
151+
@Test
152+
fun `serialize column with name 'value'`() {
153+
val df = dataFrameOf("a")(dataFrameOf("value")(1, 2, 3))
154+
val json = df.toJson()
155+
json shouldContain "\"value\":1"
156+
val df1 = DataFrame.readJsonStr(json)
157+
df shouldBe df1
158+
}
159+
142160
@Test
143161
fun `literal json field named 'value'`() {
144162
val json = """

0 commit comments

Comments
 (0)