2013-06-16 2 views
6

Ищет хороший пример полиморфный сериализации десериализации с использованием Джексона СкалеИщет хороший пример полиморфный сериализации десериализации с использованием Джексона Scala

получил исключение:

Исключения в потоке «основного» Blockquote org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Непризнанные поле "животные" (Zoo класс), не помеченных как игнорируемые

после попытки следующий код:

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 
    } 

} 

файл input.json

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

ответ

4

Ok, Понял здесь рабочий пример с Скале на основе 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": "dog", "name": "Spike", "breed": "mutt", "color": "red"},{ «тип»: «кошки», «имя»: «Пушистый», «favoriteToy»: «паук кольцо»} ]}

5

Если вы делаете полиморфные десериализации в Scala я настоятельно рекомендую используя классы классов и модуль Scala от Jackson.

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, какая версия Jackson и версия Scala вы запустили? Я получаю com.fasterxml.jackson.databind.JsonMappingException: не удается создать экземпляр TestJackson $ Animal, проблема: абстрактные типы либо должны быть сопоставлены конкретным типам, имеют настраиваемый десериализатор, либо создаются с дополнительной информацией о типе на Scala 2.10 .4 с последним Jackson 2.4.3 –

+0

Я обновил свое сообщение, чтобы включить конкретные импортные (эта ошибка звучит как неправильный импорт). Это должно работать на всех версиях Scala 2.9+ и Jackson 2.2+ (если не раньше). Я специально использовал Scala 2.11.2 и Jackson 2.4.3. Пока есть комбинация Jackson-module-scala, построенная для комбинации, она должна работать. Вы можете найти их здесь: http://search.maven.org/#search%7Cga%7C1%7Cjackson-module-scala – Nate

+0

Отлично, работает сейчас. Благодаря! –

Смежные вопросы