9

В Play 2.1 мы используем что-то вроде ниже, чтобы получить объект существа из JSON через чтение.Play JSON Combinators

implicit val creatureReads = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean] and 
    (__ \ "weight").read[Float] 
)(Creature.apply _) 

родственника нового в Scala, я пытаюсь понять, есть ли другой способ, чтобы построить объект существ без использования метода Apply? Можно ли создать анонимную функцию для создания объекта вместо того, чтобы полагаться на заявку?

У меня есть случаи, когда большинство полей в моих объектах могут отсутствовать, но я бы хотел построить объект из того, что у меня есть. Лучше ли просто определить один READ для объекта и использовать readnullable для каждого из полей?

У меня также были сложные условные выражения, так что было бы проще определить пользовательские функции для его создания, а не пытаться захватить все случаи в одном Reader?

ответ

18

Да, конечно, метод apply - это всего лишь метод, который принимает все параметры классов случаев. Это переводится примерно к следующему:

implicit val creatureReads = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean] and 
    (__ \ "weight").read[Float] 
)((name: String, isDead: Boolean, weight: Float) => new Creature(name, isDead, weight)) 

Для отсутствующих полей вы действительно должны использовать readNullable и обернуть классы полей Option. Если есть разумные значения по умолчанию для ваших дополнительных полей, вы можете вместо этого использовать orElse(Reads.pure(value)).

Допустим weight является необязательным и isDead ложна по умолчанию:

implicit val creatureReads = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and 
    (__ \ "weight").readNullable[Float] 
)(Creature.apply _) 

Иногда вы даже не хотите что-то из JSON читать. В этом случае одна возможность передачи значения в явном виде:

def creatureReads(createdAt: DateTime) = (
    (__ \ "name").read[String] and 
    (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and 
    (__ \ "weight").readNullable[Float] and 
    (__ \ "createdAt").read(createdAt) 
)(Creature.apply _) 
+0

Спасибо, что очистили его для меня. Но еще один вопрос о JSErrors, какой бы чистый способ указать пользовательскую ошибку вместо «path \ foo» не найден? Есть ли где-нибудь, что я могу положить в Чтение? –

+0

Не для чтения по умолчанию, но это зависит от вашего варианта использования. Можете ли вы опубликовать отдельный вопрос? –

+0

Несомненно, можете ли вы взглянуть на http://stackoverflow.com/questions/17818924/play-framework-json-reader-and-custom-jserrors –

-1

Я считаю, что это будет гораздо более удобным для чтения:

implicit val createReads = new Reads[Creature] { 
    override def reads(json: JsValue): JsResult[Creature] = { 
    val creature = Creature(
     name = (json \ "name").as[String], 
     isDead = (json \ "isDead").as[Boolean], 
     weight = (json \ "weight").as[Float] 
    ) 
    JsSuccess(creature) 
    } 
} 
+0

Это не предоставляет случаи «JsError», нет? Или автоматически выполняет обработку исключений, созданных в 'reads', и предоставляет для них' JsError'? – advait