25

I need to load a JSON file with a list of cities in one of my controllers, in order to pass it to a view afterwards.

I have placed the file here: app/assets/jsons/countriesToCities.json
(By the way: is this an appropriate location, or should I place it somewhere else?)

I have read the docs and I can see it is possible to create a JsValue from a string: https://www.playframework.com/documentation/2.4.x/ScalaJson#Using-string-parsing

I want to create a JsValue in a similar fashion. The difference is that I want to load the content from a file, not from a string... I haven't found any code snippet on how to do this, unfortunately.
Do I have to use something else to read the file into a string and only then use the parse method on that string?

Code snippets with examples on how to do this in the answers will be highly appreciated! :)

Thank you very much in advance!

2
  • Possible duplicate of how to read a file from server in play framework Commented Dec 17, 2015 at 14:33
  • 1
    Not really a duplicate @Mr.V. . But together with Dylan's answer, I think I will manage to solve it! Thanks! Commented Dec 29, 2015 at 15:54

4 Answers 4

27

Looks like the comment about the possible duplicate is how to read a file from your app/assets folder. My answer is about how to parse Json from a stream. Combine the two and you should be good to go.

Json.parse accepts a few different argument types, one of which is InputStream.

val stream = new FileInputStream(file)
val json = try {  Json.parse(stream) } finally { stream.close() }

P.S. When you can't find what you're looking for in the written docs, the API Docs are a good place to start.

Sign up to request clarification or add additional context in comments.

3 Comments

FileInputStream belongs to java.io, but I am using Scala + Play, not Java + Play. Do I really have to use the java.io, or is there any other way?
Short answer is no. Long answer: Scala doesn't have much built-in functionality for IO. The scala.io.Source object is your closest bet - you could use that to load a file to a string, then pass that string to Json.parse. You could also look into other libraries with IO solutions, but that seems like too much effort to replace two lines of code.
I should note that since you are using Scala + Play, you are really using Scala + Java + Play. You can still use java.io without losing Scala.
20

Here is how I managed to solve it:

val source: String = Source.fromFile("app/assets/jsons/countriesToCities.json").getLines.mkString
val json: JsValue = Json.parse(source)

Thanks for the help! :)

2 Comments

Json.parse can read directly from a stream, so it's better to use the InputStream version rather than getting the lines, making a string out of them, and then parsing it.
The .getLines is not necessary here. Also, it'd be better to close the result of the fromFile call (a io.Source instance).
6

From Play 2.6, Environment has the getExistingFile, getFile, resource and resourceAsStream methods, E.g.:

class Something @Inject (environment: play.api.Environment) {
  // ...
  environment.resourceAsStream("data.json") map ( Json.parse(_) )

(Note, in this case data.json is inside the conf folder)

https://www.playframework.com/documentation/2.6.x/api/scala/index.html#play.api.Environment

Comments

0

I usually need few small dictionaries to live in memory in order to build some plain LUTs (LookUp Tables). In order to achieve that I use the following piece of code (please it is worth noting I am using latest Play 2.6):

def loadJSONFromFilename(filename: String): Option[JsValue] =
  Option(Source.fromFile(filename).mkString)
    .map(Json.parse)

Using the previous function is just a matter of passing a filename path. Tailoring this to be used with Play you might need to place your file in a resource folder and to enable it you need to place this in your build.sbt file:

// include resources into the unversal zipped package using sbt dist
mappings in Universal ++= directory(baseDirectory.value / "resources")

Thus, you can use this resource folder this way in your Play class:

lazy val lutFilePath: Path = 
  Paths.get(env.rootPath.getAbsolutePath, "resources", "lut.json")
lazy val lutJson = loadJSONFromFilename(lutFilePath.toString)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.