2013-06-16 19 views
6

Patrząc na dobry przykład polimorficznych serializacji deserializacji stosując Jacksona scalaPatrząc na dobry przykład polimorficznych serializacji deserializacji stosując Jacksona scala

dostaje wyjątek:

wyjątek w wątku „główne” blockquote org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Nierozpoznane pole "zwierzęta" (klasa zoo), nie oznaczone jako ignorable

po wypróbowaniu następujący kod:

import org.codehaus.jackson.annotate.{ JsonTypeInfo, JsonSubTypes } 
    import org.codehaus.jackson.annotate.JsonSubTypes.Type 

    @JsonTypeInfo(
     use = JsonTypeInfo.Id.NAME, 
     include= JsonTypeInfo.As.PROPERTY, 
     property = "type" 
    ) 
    @JsonSubTypes(Array(
     new Type(value= classOf[Cat] , name = "cat"), 
     new Type(value= classOf[Dog] , name = "dog") 
    ) 
    ) 
    abstract class Animal { 
     val name:String = "NoName" 

    } 
class Cat extends Animal{ 
    val favoriteToy = "edi" 
} 
class Dog extends Animal{ 
    val breed = "German Shepherd" 
    val color = "brown" 
} 
class Zoo { 
    val animals = new scala.collection.mutable.ListBuffer[Animal] 
} 
import org.codehaus.jackson.map.ObjectMapper 

object Foo { 
    def main (args:Array[String]) { 
    val mapper = new ObjectMapper() 
    mapper.setPropertyNamingStrategy(CamelCaseNamingStrategy) 
    val source = scala.io.Source.fromFile("input.json") 
    val input = source.mkString 
    source.close 
    val zoo = mapper.readValue(input,classOf[Zoo]) 
    println(mapper.writeValueAsString(zoo)) 
    } 
import org.codehaus.jackson.map.introspect.{AnnotatedField, AnnotatedMethod} 
import org.codehaus.jackson.map.{MapperConfig, PropertyNamingStrategy} 

object CamelCaseNamingStrategy extends PropertyNamingStrategy{ 
override def nameForGetterMethod (config: MapperConfig[_], method: AnnotatedMethod, defaultName: String) = 
{ 
    translate(defaultName) 
} 

override def nameForSetterMethod (config: MapperConfig[_], method: AnnotatedMethod, defaultName: String) = { 
    translate(defaultName) 
} 

    override def nameForField (config: MapperConfig[_], field: AnnotatedField, defaultName: String) = { 
    translate(defaultName) 
    } 

    def translate(defaultName:String) = { 
    val nameChars = defaultName.toCharArray 
    val nameTranslated = new StringBuilder(nameChars.length*2) 
    for (c <- nameChars){ 
     if (Character.isUpperCase(c)){ 
     nameTranslated.append("_") 
     } 
     nameTranslated.append(Character.toLowerCase(c)) 
    } 
    nameTranslated.toString 
    } 

} 

plik input.json

{ 
"animals": 
    [ 
    {"type":"dog","name":"Spike","breed":"mutt","color":"red"}, 
    {"type":"cat","name":"Fluffy","favoriteToy":"spider ring"} 
    ] 
} 

Odpowiedz

4

Ok, rozumiem tutaj jest przykład pracy z Scala na podstawie Deserialize JSON with Jackson into Polymorphic by Programmer Bruce:

import org.codehaus.jackson.annotate.JsonSubTypes.Type 
import org.codehaus.jackson.annotate.{JsonSubTypes, JsonTypeInfo} 

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME, 
    include= JsonTypeInfo.As.PROPERTY, 
    property = "type" 
) 
@JsonSubTypes(Array(
    new Type(value= classOf[Cat] , name = "cat"), 
    new Type(value= classOf[Dog] , name = "dog") 
) 
) 
abstract class Animal { 
    var name:String ="" 

} 

class Dog extends Animal{ 
    var breed= "German Shepherd" 
    var color = "brown" 
} 

class Cat extends Animal{ 
    var favoriteToy:String = "nothing" 
} 


class Zoo { 
    var animals = new Array[Animal](5) 
} 


import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility 
import org.codehaus.jackson.annotate.JsonMethod 
import org.codehaus.jackson.map.{DeserializationConfig, ObjectMapper} 

object Foo { 
    def main (args:Array[String]) { 
    val mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD,Visibility.ANY) 
    mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES,false) 
    val source = scala.io.Source.fromFile("/input.json") 
    val input = source.mkString 
    println("input " + input) 
    source.close 
    val zoo = mapper.readValue(input,classOf[Zoo]) 

    println(mapper.writeValueAsString(zoo)) 
    } 

} 

file: input.json {"animals": [ {"type": "pies", "name": "Spike", "breed": "mutt", "color": "red"}, { "type": "kot", "name": "puszysty", "favoriteToy": "pierścień pająk"} ]}

5

Jeśli robisz polimorficzny deserializacji w Scala Chciałbym gorąco polecam użycie klas przypadków i modułu scala Jacksona.

object Test { 
    import com.fasterxml.jackson.annotation.JsonSubTypes.Type 
    import com.fasterxml.jackson.annotation.{JsonSubTypes, JsonTypeInfo} 
    import com.fasterxml.jackson.databind.ObjectMapper 
    import com.fasterxml.jackson.module.scala.DefaultScalaModule 
    import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper 

    @JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME, 
    include = JsonTypeInfo.As.PROPERTY, 
    property = "type" 
) 
    @JsonSubTypes(Array(
    new Type(value = classOf[Cat], name = "cat"), 
    new Type(value = classOf[Dog], name = "dog") 
)) 
    trait Animal 

    case class Dog(name: String, breed: String, leash_color: String) extends Animal 
    case class Cat(name: String, favorite_toy: String) extends Animal 
    case class Zoo(animals: Iterable[Animal]) 

    def main(args: Array[String]): Unit = { 
    val objectMapper = new ObjectMapper with ScalaObjectMapper 
    objectMapper.registerModule(DefaultScalaModule) 

    val dogStr = """{"type": "dog", "name": "Spike", "breed": "mutt", "leash_color": "red"}""" 
    val catStr = """{"type": "cat", "name": "Fluffy", "favorite_toy": "spider ring"}""" 
    val zooStr = s"""{"animals":[$dogStr, $catStr]}""" 

    val zoo = objectMapper.readValue[Zoo](zooStr) 

    println(zoo) 
    // Prints: Zoo(List(Dog(Spike,mutt,red), Cat(Fluffy,spider ring))) 
    } 
} 
+0

Nate, na jaką wersję Jackson i do której wersji Scala go użyłeś? Dostaję com.fasterxml.jackson.databind.JsonMappingException: Nie można skonstruować instancji TestJackson $ Animal, problem: typy abstrakcyjne muszą być odwzorowane na konkretne typy, mieć niestandardowy deserializer lub być tworzone z dodatkowymi informacjami o typie na Scali 2.10 .4 z najnowszym Jacksonem 2.4.3 –

+0

Zaktualizowałem swój post, aby uwzględnić specyficzny import (ten błąd brzmi jak niepoprawny import). Powinno to działać we wszystkich wersjach Scala 2.9+ i Jackson 2.2+ (jeśli nie wcześniej). Szczególnie używałem Scala 2.11.2 i Jackson 2.4.3. Dopóki jest jarson-moduł-scala słoik zbudowany dla kombinacji, powinien działać. Możesz je znaleźć tutaj: http://search.maven.org/#search%7Cga%7C1%7Cjackson-module-scala – Nate

+0

Świetnie, działa teraz. Dzięki! –

Powiązane problemy