FasterXML / FasterXML/jackson-module-scala

Custom serializer with type information and yaml output

オープン
#192 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る
主要言語
Scala
スター
506
フォーク
138
平均マージ
3時間 6分
マージ済み PR(30日)
48

説明

Hi, I'm trying to write a custom serializer for an Nd4j array (see http://nd4j.org). I was about to get it working with json but when I try yaml output I get an exception:

``` scala
Cause: com.fasterxml.jackson.dataformat.yaml.snakeyaml.emitter.EmitterException: expected NodeEvent, but got
at com.fasterxml.jackson.dataformat.yaml.snakeyaml.emitter.Emitter.expectNode(Emitter.java:409)
at com.fasterxml.jackson.dataformat.yaml.snakeyaml.emitter.Emitter.access$1600(Emitter.java:63)
at com.fasterxml.jackson.dataformat.yaml.snakeyaml.emitter.Emitter$ExpectBlockMappingValue.expect(Emitter.java:651)
at com.fasterxml.jackson.dataformat.yaml.snakeyaml.emitter.Emitter.emit(Emitter.java:217)
at com.fasterxml.jackson.dataformat.yaml.YAMLGenerator.close(YAMLGenerator.java:308)
at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3398)
at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:2779)
```

In order to simplify the test I created dummy classes for `Nd4j` so I know the issue is not specific to that package. This test case:

``` scala
import com.fasterxml.jackson.databind.JsonSerializer
//import org.nd4j.linalg.api.ndarray.INDArray
import com.fasterxml.jackson.core.JsonGenerator
import com.fasterxml.jackson.databind.SerializerProvider
//import org.nd4j.linalg.api.buffer.DataBuffer
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
import com.fasterxml.jackson.databind.jsontype.TypeSerializer
//import org.nd4j.linalg.factory.Nd4j
import com.fasterxml.jackson.annotation.JsonTypeInfo
import org.scalatest.FunSuite

// Dummy INDArray
class INDArray {
val _data = new DataBuffer
def shape() = Array[Int](1, 3)
def data = _data
def ordering() = 'f'
}

// Dummy DataBuffer
class DataBuffer {
def dataType = 1
def asBytes() = Array[Byte](1, 2, 3)
}

// Custom serializer for INDArray
class NDArraySerializer extends JsonSerializer[INDArray] {

def serialize(
value: INDArray,
jgen: JsonGenerator,
provider: SerializerProvider) {

jgen.writeStartObject()

jgen.writeArrayFieldStart("shape")
for (i <- value.shape()) jgen.writeNumber(i)
jgen.writeEndArray()

val dtype =
if (value.data.dataType == 1 /*DataBuffer.FLOAT*/ )
"float"
else
"double"
jgen.writeStringField("dtype", dtype)

jgen.writeStringField("order", value.ordering().toString())

jgen.writeBinaryField("data", value.data.asBytes())

jgen.writeEndObject()
}

override def serializeWithType(
value: INDArray,
jgen: JsonGenerator,
provider: SerializerProvider,
typeSer: TypeSerializer) {

typeSer.writeTypePrefixForObject(value, jgen)
serialize(value, jgen, provider)
typeSer.writeTypeSuffixForObject(value, jgen)
}
}

class TestYAML extends FunSuite {

test("yaml") {

try {
val nd4jModule = new SimpleModule()

nd4jModule.addSerializer(classOf[INDArray], new NDArraySerializer())

val jsonMapper = new ObjectMapper

jsonMapper.registerModule(DefaultScalaModule)

jsonMapper.registerModule(nd4jModule)

jsonMapper.enableDefaultTyping(
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY)

val yamlMapper = new ObjectMapper(new YAMLFactory)

yamlMapper.registerModule(DefaultScalaModule)

yamlMapper.registerModule(nd4jModule)

yamlMapper.enableDefaultTyping(
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY)

val array = new INDArray

jsonMapper.writeValueAsString(array)

yamlMapper.writeValueAsString(array)
}
catch {
case e: Throwable => fail("shouldn't throw an exception.", e)
}
}
}

```

If I comment out the `enableDefaultTyping` call it works.

コントリビューションガイド

このリポジトリのコントリビューションガイドは索引されていません

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。