Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@boosh
Copy link
Contributor

@boosh boosh commented Oct 24, 2016

Pull Request Checklist

  • Have you read How to write the perfect pull request?
  • Have you read through the contributor guidelines?
  • Have you signed the Lightbend CLA?
  • Have you [squashed your commits]? (Optional, but makes merge messages nicer.)
  • Have you added copyright headers to new files?
  • Have you checked that both Scala and Java APIs are updated?
  • Have you updated the documentation for both Scala and Java sections?
  • Have you added tests for any changed functionality?

Mostly...

Helpful things

Fixes

Fixes #xxxx

Purpose

What does this PR do?

Adds a summary of the capabilities of the Scala JSON package so users know it's able to convert to and from case classes automatically. Also provided an example of doing that.

Background Context

Why did you take this approach?

The first page of the JSON docs is pretty intimidating for new users. Now it highlights some of the features of the package so users don't get bogged down in the details if they just want to serialise to/from case classes.

References

Are there any relevant issues / PRs / mailing lists discussions?
#6663

@wsargent
Copy link
Member

/home/travis/build/playframework/playframework/documentation/manual/working/scalaGuide/main/json/code/ScalaJsonAutomatedSpec.scala:160: identifier expected but string literal found.
[error]       val resident = Resident(name: "Fiver", age: 4, role: None)
[error]                                     ^
[error] /home/travis/build/playframework/playframework/documentation/manual/working/scalaGuide/main/json/code/ScalaJsonAutomatedSpec.scala:166: ')' expected but '}' found.
[error]     }
[error]     ^

## The Play JSON library

The [`play.api.libs.json`](api/scala/play/api/libs/json/package.html) package contains data structures for representing JSON data and utilities for converting between these data structures and other data representations. Types of interest are:
The [`play.api.libs.json`](api/scala/play/api/libs/json/package.html) package contains data structures for representing JSON data and utilities for converting between these data structures and other data representations. Some of the features of this package are:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also worth mentioning that it can be used outside a Play application as an independent library?

libraryDependencies += "com.tyesafe.play" %% "play-json" % playVersion


@[auto-custom-naming-format](code/ScalaJsonAutomatedSpec.scala)

### Bringing it all together
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like an odd place to put this example, in the section about custom naming strategies.

I would probably just expand the examples we already have in the first section. We already show how to generate a Reads or Writes for a case class, but don't show it being used.

"age" : 4
}""")

Json.fromJson[Resident](jsonString)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be clearer to assign to a variable:

val residentFromJson: Resident = Json.fromJson[Resident](jsonString)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestions. I've updated my branch.


val resident = Resident(name="Fiver", age=4, role=None)

Json.toJson(resident)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, would be useful to have a variable or something with a type to indicate what this returns:

val residentJson: JsValue = Json.toJson(resident)

"age" : 4
}""")

val residentFromJson: JsResult[Resident] = Json.fromJson[Resident](jsonString)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's necessary/useful to explain how to extract a value from a JsResult safely (using pattern matching, fold, etc.), or is this self-explanatory to you given the other documentation?

@schmitch
Copy link
Contributor

well maybe we should also summarize that one could use a body parser where he can either use json or tolerantJson and maybe with / without reads. I guess the latter one is explained nowhere.
I mean something like def bla = Action(parse.json[MyClass]) or def bla = Action(parse.json(jsonReads) I mean these two have still the shortcoming that they return a html site.

Basically what I wanted to say is that many people will probably skip the BodyParser docs and directly read into https://www.playframework.com/documentation/2.5.x/ScalaJsonHttp where we only explain BodyParsers.parse.json and not any other method.

@boosh
Copy link
Contributor Author

boosh commented Oct 26, 2016

@schmitch That's super useful. I didn't know Play could do that. I'll add that in as well.

@boosh
Copy link
Contributor Author

boosh commented Oct 26, 2016

OK I've added an example of a body parser typed with a case class. I can't really spend much more time on this so please merge it (unless there are minor grammatical errors/typos, etc.).

Thanks

@wsargent
Copy link
Member

If you're processing json in a body parser, you should use validate, i.e.

def validateJson[A : Reads] = parse.json.validate(
 _.validate[A].asEither.left.map(e => BadRequest(JsError.toFlatJson(e)))
)

So you can process the error result in the event of bad JSON.

@boosh
Copy link
Contributor Author

boosh commented Oct 26, 2016

@wsargent I've not got as far as validation yet (i.e. I'm new to Play and don't know how to do it).

How does your example apply to what I've added? For instance, I've written that you need to forego validation if you use a typed body parser. If that's not right, please can you show me how my code needs to be updated to allow a typed body parser to validate a request.

Thanks

@schmitch
Copy link
Contributor

schmitch commented Oct 26, 2016

@boosh what @wsargent actually said was that if you use BodyParsers.parse.json[Place] it will return a HTML page.
However if you use his snippet:

def validateJson[A : Reads] = parse.json.validate(
    _.validate[A].asEither.left.map(e => BadRequest(JsError.toJson(e)))
  )

you can actually return a JSON response also in a Controller you don't need to write BodyParsers.
His Snippet is basically creating a "custom" BodyParser based on a existing one. You can just use it like that:

def myAction = Action(validateJson[MyClass]) { implicit request => Ok }

@gmethvin
Copy link
Member

Also the advantage of that approach is that it parses your body into the correct type, so request.body actually is of type A (the case class parsed from JSON) inside your action, instead of a plain JsValue.

@boosh
Copy link
Contributor Author

boosh commented Oct 26, 2016

OK that's really cool thanks. I'll update my PR again. It did seem a bit weird that using a typed body parser prevented validation...

- [[Automatic conversion|ScalaJsonAutomated]] to and from case classes with minimal boilerplate. If you want to get up and running quickly with minimal code, this is probably the place to start.
- [[Custom validation|ScalaJsonCombinators#Validation-with-Reads]] while parsing.
- [[Automatic parsing|ScalaBodyParsers#The-default-body-parser]] of JSON in request bodies, with auto-generated errors if content isn't parseable or incorrect Content-type headers are supplied.
- Can be used outside of a Play application as a standalone library. Just add `libraryDependencies += "com.tyesafe.play" %% "play-json" % playVersion` to your `build.sbt` file.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is typo here. "tyesafe" must be "typesafe"

libraryDependencies += "com.typesafe.play" %% "play-json" % playVersion

is right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I think there is redundant double percent symbol.
@gmethvin , is it must be single?

@gmethvin gmethvin merged commit f6f402e into playframework:master Oct 28, 2016
gmethvin pushed a commit that referenced this pull request Oct 28, 2016
* Summarize the JSON package and provide relevant links.

* Fix code samples

* Incorporate suggestions

* Standalone not stand-alone

* Grammar

* Incorporate suggestions, including an example of a body parser typed with a case class.

* Add an example of using the body parser to validate JSON as well

* Fix typo
@boosh boosh deleted the json-documentation branch October 30, 2016 08:22
@mkurz mkurz added this to the 2.5.10 milestone Dec 6, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants