diff --git a/admin/app/controllers/admin/CommercialController.scala b/admin/app/controllers/admin/CommercialController.scala index 0f563f1c1071..2ba143ddd9cc 100644 --- a/admin/app/controllers/admin/CommercialController.scala +++ b/admin/app/controllers/admin/CommercialController.scala @@ -126,7 +126,7 @@ class CommercialController( val lineItems: Seq[GuLineItem] = Store.getDfpLineItemsReport().lineItems filter (_.orderId.toString == orderId) Cached(5.minutes) { - JsonComponent(Json.toJson(lineItems)) + JsonComponent.fromWritable(lineItems) } } @@ -144,7 +144,7 @@ class CommercialController( }) getOrElse Nil Cached(5.minutes) { - JsonComponent(Json.toJson(previewUrls)) + JsonComponent.fromWritable(previewUrls) } } diff --git a/admin/app/football/controllers/PlayerController.scala b/admin/app/football/controllers/PlayerController.scala index 661c639a36b0..2dac7fa04932 100644 --- a/admin/app/football/controllers/PlayerController.scala +++ b/admin/app/football/controllers/PlayerController.scala @@ -152,7 +152,7 @@ class PlayerController(val wsClient: WSClient, val controllerComponents: Control ), ), ) - Cached(600)(JsonComponent(responseJson)) + Cached(600)(JsonComponent.fromWritable(responseJson)) } } } diff --git a/applications/app/controllers/GalleryController.scala b/applications/app/controllers/GalleryController.scala index c147578b20ad..4c9b65dfbbe6 100644 --- a/applications/app/controllers/GalleryController.scala +++ b/applications/app/controllers/GalleryController.scala @@ -39,7 +39,7 @@ class GalleryController(contentApiClient: ContentApiClient, val controllerCompon val index = request.getIntParameter("index") getOrElse 1 lookup(path, index, isTrail = false) map { case Right(other) => RenderOtherStatus(other) - case Left(model) => Cached(model) { JsonComponent(model.gallery.lightbox.javascriptConfig) } + case Left(model) => Cached(model) { JsonComponent.fromWritable(model.gallery.lightbox.javascriptConfig) } } } diff --git a/applications/app/controllers/ImageContentController.scala b/applications/app/controllers/ImageContentController.scala index f7e7c7800fbf..2f5cd5540e21 100644 --- a/applications/app/controllers/ImageContentController.scala +++ b/applications/app/controllers/ImageContentController.scala @@ -65,7 +65,7 @@ class ImageContentController( case _ => None }, ) - Cached(CacheTime.Default)(JsonComponent(JsArray(lightboxJson))) + Cached(CacheTime.Default)(JsonComponent.fromWritable(JsArray(lightboxJson))) } } } diff --git a/applications/app/controllers/MediaController.scala b/applications/app/controllers/MediaController.scala index 40e2807d3bf3..825f576505c1 100644 --- a/applications/app/controllers/MediaController.scala +++ b/applications/app/controllers/MediaController.scala @@ -33,7 +33,7 @@ class MediaController(contentApiClient: ContentApiClient, val controllerComponen case Left(model) => MediaInfo(expired = false, shouldHideAdverts = model.media.content.shouldHideAdverts) case Right(other) => MediaInfo(expired = other.header.status == GONE, shouldHideAdverts = true) } map { mediaInfo => - Cached(60)(JsonComponent(withRefreshStatus(Json.toJson(mediaInfo).as[JsObject]))) + Cached(60)(JsonComponent.fromWritable(withRefreshStatus(Json.toJson(mediaInfo).as[JsObject]))) } } diff --git a/commercial/app/controllers/BookOffersController.scala b/commercial/app/controllers/BookOffersController.scala index 3fdff8d165be..c65c1ae4e349 100644 --- a/commercial/app/controllers/BookOffersController.scala +++ b/commercial/app/controllers/BookOffersController.scala @@ -30,12 +30,12 @@ class BookOffersController( def getBook: Action[AnyContent] = Action { implicit request => lazy val failedLookupResult: Result = Cached(30.seconds)(JsonNotFound())(request) - lazy val badRequestResponse: Result = Cached(1.day)(JsonComponent(JsNull))(request) + lazy val badRequestResponse: Result = Cached(1.day)(JsonComponent.fromWritable(JsNull))(request) specificId match { case Some(isbn) if isValidIsbn(isbn) => bookFinder.findByIsbn(isbn) map { book: Book => - Cached(1.hour)(JsonComponent(Json.toJson(book))) + Cached(1.hour)(JsonComponent.fromWritable(book)) } getOrElse failedLookupResult case Some(invalidIsbn) => log.error(s"Book lookup called with invalid ISBN '$invalidIsbn'. Returning empty response.") @@ -49,9 +49,8 @@ class BookOffersController( def getBooks: Action[AnyContent] = Action { implicit request => - val json: JsValue = Json.toJson(booksSample(specificIds, segment)) Cached(60.seconds) { - JsonComponent(json) + JsonComponent.fromWritable(booksSample(specificIds, segment)) } } } diff --git a/commercial/app/controllers/ContentApiOffersController.scala b/commercial/app/controllers/ContentApiOffersController.scala index 41ae09a44927..23b675cf9fa8 100644 --- a/commercial/app/controllers/ContentApiOffersController.scala +++ b/commercial/app/controllers/ContentApiOffersController.scala @@ -62,11 +62,11 @@ class ContentApiOffersController( case Nil => Cached(componentNilMaxAge) { jsonFormat.nilResult } case content if isMulti => Cached(1.hour) { - JsonComponent(CapiMultiple.fromContent(content, Edition(request))) + JsonComponent.fromWritable(CapiMultiple.fromContent(content, Edition(request))) } case first :: _ => Cached(1.hour) { - JsonComponent(CapiSingle.fromContent(first, Edition(request))) + JsonComponent.fromWritable(CapiSingle.fromContent(first, Edition(request))) } } diff --git a/commercial/app/controllers/JobsController.scala b/commercial/app/controllers/JobsController.scala index f0986cfe1066..042d56cdfae3 100644 --- a/commercial/app/controllers/JobsController.scala +++ b/commercial/app/controllers/JobsController.scala @@ -20,7 +20,7 @@ class JobsController(jobsAgent: JobsAgent, val controllerComponents: ControllerC def getJobs: Action[AnyContent] = Action { implicit request => Cached(60.seconds) { - JsonComponent(jobSample(specificIds, segment)) + JsonComponent.fromWritable(jobSample(specificIds, segment)) } } } diff --git a/commercial/app/controllers/LiveEventsController.scala b/commercial/app/controllers/LiveEventsController.scala index 8d06639c4f7e..4f080f46893e 100644 --- a/commercial/app/controllers/LiveEventsController.scala +++ b/commercial/app/controllers/LiveEventsController.scala @@ -16,7 +16,7 @@ class LiveEventsController(liveEventAgent: LiveEventAgent, val controllerCompone for { id <- specificId event <- liveEventAgent.specificLiveEvent(id) - } yield Cached(componentMaxAge) { JsonComponent(event) } + } yield Cached(componentMaxAge) { JsonComponent.fromWritable(event) } } getOrElse Cached(componentNilMaxAge) { jsonFormat.nilResult } } } diff --git a/commercial/app/controllers/Multi.scala b/commercial/app/controllers/Multi.scala index 7e77f10d94bb..603d8a029da7 100644 --- a/commercial/app/controllers/Multi.scala +++ b/commercial/app/controllers/Multi.scala @@ -72,7 +72,7 @@ class Multi( if (offerTypes.size == contents.size) { Cached(componentMaxAge) { - JsonComponent(JsArray((offerTypes zip contents).map { + JsonComponent.fromWritable(JsArray((offerTypes zip contents).map { case (contentType, content) => Json.obj( "type" -> contentType, diff --git a/commercial/app/controllers/TrafficDriverController.scala b/commercial/app/controllers/TrafficDriverController.scala index 729487b8be73..e8a0d400ef73 100644 --- a/commercial/app/controllers/TrafficDriverController.scala +++ b/commercial/app/controllers/TrafficDriverController.scala @@ -44,7 +44,7 @@ class TrafficDriverController( case None => Cached(componentNilMaxAge) { jsonFormat.nilResult } case Some(content) => Cached(60.seconds) { - JsonComponent(TrafficDriver.fromContent(content, Edition(request))) + JsonComponent.fromWritable(TrafficDriver.fromContent(content, Edition(request))) } } diff --git a/commercial/app/controllers/TravelOffersController.scala b/commercial/app/controllers/TravelOffersController.scala index b8a013ec73e1..81c67f7fdcf5 100644 --- a/commercial/app/controllers/TravelOffersController.scala +++ b/commercial/app/controllers/TravelOffersController.scala @@ -19,9 +19,8 @@ class TravelOffersController(travelOffersAgent: TravelOffersAgent, val controlle def getTravel: Action[AnyContent] = Action { implicit request => - val json = Json.toJson(travelSample(specificIds, segment)) Cached(60.seconds) { - JsonComponent(json) + JsonComponent.fromWritable(travelSample(specificIds, segment)) } } } diff --git a/commercial/app/controllers/nonRefreshableLineItemsController.scala b/commercial/app/controllers/nonRefreshableLineItemsController.scala index 7aac95821a71..06a988b156b4 100644 --- a/commercial/app/controllers/nonRefreshableLineItemsController.scala +++ b/commercial/app/controllers/nonRefreshableLineItemsController.scala @@ -15,11 +15,9 @@ class nonRefreshableLineItemsController(val controllerComponents: ControllerComp def getIds: Action[AnyContent] = Action { implicit request => val nonRefreshableLineItems: Seq[Long] = DfpAgent.nonRefreshableLineItemIds() - val json = Json.toJson(nonRefreshableLineItems) - Cors( Cached(15.minutes) { - JsonComponent(json) + JsonComponent.fromWritable(nonRefreshableLineItems) }, None, None, diff --git a/common/app/common/JsonComponent.scala b/common/app/common/JsonComponent.scala index b4107f35275a..fdfb0778cdc1 100644 --- a/common/app/common/JsonComponent.scala +++ b/common/app/common/JsonComponent.scala @@ -14,7 +14,7 @@ object JsonComponent extends Results with implicits.Requests { def withRefreshStatus(obj: JsObject): JsValue = obj + ("refreshStatus" -> toJson(AutoRefreshSwitch.isSwitchedOn)) - def apply[A](value: A)(implicit request: RequestHeader, writes: Writes[A]): RevalidatableResult = + def fromWritable[A](value: A)(implicit request: RequestHeader, writes: Writes[A]): RevalidatableResult = resultFor( request, Json.stringify(Json.toJson(value)), diff --git a/common/test/common/JsonComponentTest.scala b/common/test/common/JsonComponentTest.scala index c41a7c6c9896..947915425960 100644 --- a/common/test/common/JsonComponentTest.scala +++ b/common/test/common/JsonComponentTest.scala @@ -61,7 +61,7 @@ class JsonComponentTest extends AnyFlatSpec with Matchers with WithTestExecution val result = Future { implicit val request = FakeRequest("GET", "http://foo.bar.com/data.json") - JsonComponent(JsonComponent.withRefreshStatus(obj("name" -> "foo"))).result + JsonComponent.fromWritable(JsonComponent.withRefreshStatus(obj("name" -> "foo"))).result } contentType(result) should be(Some("application/json")) diff --git a/discussion/app/controllers/CommentCountController.scala b/discussion/app/controllers/CommentCountController.scala index 0976d88ccc4a..33132a9f7051 100644 --- a/discussion/app/controllers/CommentCountController.scala +++ b/discussion/app/controllers/CommentCountController.scala @@ -17,7 +17,7 @@ class CommentCountController(val discussionApi: DiscussionApiLike, val controlle val counts = discussionApi.commentCounts(shortUrls) counts map { counts => Cached(300) { - JsonComponent( + JsonComponent.fromWritable( JsObject(Seq("counts" -> JsArray(counts.map(_.toJson)))), ) } diff --git a/facia/app/controllers/FaciaController.scala b/facia/app/controllers/FaciaController.scala index 132ee947ba11..e68589511cb2 100644 --- a/facia/app/controllers/FaciaController.scala +++ b/facia/app/controllers/FaciaController.scala @@ -77,7 +77,7 @@ trait FaciaController val onwardItems = OnwardCollection.pressedCollectionToOnwardCollection(collection) Cached(CacheTime.Facia) { - JsonComponent(onwardItems) + JsonComponent.fromWritable(onwardItems) } case None => Cached(CacheTime.NotFound)( @@ -156,9 +156,11 @@ trait FaciaController def renderFrontJsonLite(path: String): Action[AnyContent] = Action.async { implicit request => - frontJsonFapi.get(path, liteRequestType).map { - case Some(pressedPage) => Cached(CacheTime.Facia)(JsonComponent(FapiFrontJsonLite.get(pressedPage))) - case None => Cached(CacheTime.Facia)(JsonComponent(JsObject(Nil))) + frontJsonFapi.get(path, liteRequestType).map { resp => + Cached(CacheTime.Facia)(JsonComponent.fromWritable(resp match { + case Some(pressedPage) => FapiFrontJsonLite.get(pressedPage) + case None => JsObject(Nil) + })) } } @@ -211,7 +213,7 @@ trait FaciaController RevalidatableResult(Ok(body).as("text/xml; charset=utf-8"), body) } else if (request.isJson) { if (request.forceDCR) { - JsonComponent( + JsonComponent.fromWritable( DotcomFrontsRenderingDataModel( page = faciaPage, request = request, diff --git a/onward/app/controllers/CardController.scala b/onward/app/controllers/CardController.scala index ca1e851b04df..3914a4e697f5 100644 --- a/onward/app/controllers/CardController.scala +++ b/onward/app/controllers/CardController.scala @@ -57,7 +57,7 @@ class CardController( // To test a story that has no image: // /cards/opengraph/http%3A%2F%2Fwww.theguardian.com%2Fmedia%2Fgreenslade%2F2013%2Faug%2F22%2Fjournalist-safety-egypt.json - JsonComponent( + JsonComponent.fromWritable( withRefreshStatus( Json .toJson( @@ -92,7 +92,7 @@ class CardController( val firstParagraph = fragment.select("#mw-content-text > p").first firstParagraph.select(".reference").remove() - JsonComponent( + JsonComponent.fromWritable( withRefreshStatus( Json .toJson( diff --git a/onward/app/controllers/MostPopularController.scala b/onward/app/controllers/MostPopularController.scala index 3428a0b1c9bb..32ae029b8ad8 100644 --- a/onward/app/controllers/MostPopularController.scala +++ b/onward/app/controllers/MostPopularController.scala @@ -138,7 +138,7 @@ class MostPopularController( OnwardItem.contentCardToOnwardItem(contentCard) } val response = OnwardCollectionResponseDCR(tabs, mostCommented, mostShared) - Cached(900)(JsonComponent(response)) + Cached(900)(JsonComponent.fromWritable(response)) } def jsonResponseNx2(mostPopulars: Seq[MostPopularNx2], mostCards: Map[String, Option[ContentCard]])(implicit @@ -154,7 +154,7 @@ class MostPopularController( OnwardItem.contentCardToOnwardItem(contentCard) } val response = OnwardCollectionResponseDCR(tabs, mostCommented, mostShared) - Cached(900)(JsonComponent(response)) + Cached(900)(JsonComponent.fromWritable(response)) } def jsonResponse(mostPopular: MostPopular, countryCode: String)(implicit request: RequestHeader): Result = { @@ -163,7 +163,7 @@ class MostPopularController( heading = mostPopular.heading, trails = mostPopular.trails.map(OnwardItem.pressedContentToOnwardItem).take(10), ) - Cached(900)(JsonComponent(data)) + Cached(900)(JsonComponent.fromWritable(data)) } def renderPopularDay(countryCode: String): Action[AnyContent] = diff --git a/onward/app/controllers/NavigationController.scala b/onward/app/controllers/NavigationController.scala index 77cefb90ef85..4ac801423e04 100644 --- a/onward/app/controllers/NavigationController.scala +++ b/onward/app/controllers/NavigationController.scala @@ -24,7 +24,7 @@ class NavigationController(val controllerComponents: ControllerComponents) exten Edition.byId(editionId) match { case Some(edition) => val menu = SimpleMenu(edition) - Cached(900)(JsonComponent(menu)) + Cached(900)(JsonComponent.fromWritable(menu)) case None => Cached(60) { val json = Json.toJson(ApiError("Invalid edition ID.", 400)).toString() diff --git a/onward/app/controllers/PopularInTag.scala b/onward/app/controllers/PopularInTag.scala index a4bfe2b4a23a..4b27902d6fb0 100644 --- a/onward/app/controllers/PopularInTag.scala +++ b/onward/app/controllers/PopularInTag.scala @@ -40,7 +40,7 @@ class PopularInTag( val numberOfCards = if (trails.faciaItems.length == 5 || trails.faciaItems.length == 6) 4 else 8 if (request.forceDCR) { - JsonComponent( + JsonComponent.fromWritable( OnwardCollectionResponse( heading = "Related content", trails = trails.items.map(_.faciaContent).map(OnwardItem.pressedContentToOnwardItem).take(numberOfCards), diff --git a/onward/app/controllers/RelatedController.scala b/onward/app/controllers/RelatedController.scala index 3a3a60e9f328..eee7656ac984 100644 --- a/onward/app/controllers/RelatedController.scala +++ b/onward/app/controllers/RelatedController.scala @@ -62,7 +62,7 @@ class RelatedController( trails = trails.map(_.faciaContent).map(OnwardItem.pressedContentToOnwardItem).take(10), ) - JsonComponent(data) + JsonComponent.fromWritable(data) } else if (request.isJson) { val html = views.html.fragments.containers.facia_cards.container( onwardContainer(containerTitle, relatedTrails.map(_.faciaContent)), diff --git a/onward/app/controllers/RichLinkController.scala b/onward/app/controllers/RichLinkController.scala index ee31ff50678c..3b5a7d50d54c 100644 --- a/onward/app/controllers/RichLinkController.scala +++ b/onward/app/controllers/RichLinkController.scala @@ -40,7 +40,7 @@ class RichLinkController(contentApiClient: ContentApiClient, controllerComponent pillar = OnwardsUtils.normalisePillar(content.metadata.pillar), format = content.metadata.format.getOrElse(ContentFormat.defaultContentFormat), ) - Cached(900)(JsonComponent(richLink)(request, RichLink.writes)) + Cached(900)(JsonComponent.fromWritable(richLink)(request, RichLink.writes)) case Some(content) => renderContent(richLinkHtml(content), richLinkBodyHtml(content)) case None => NotFound } diff --git a/onward/app/controllers/SeriesController.scala b/onward/app/controllers/SeriesController.scala index 8ecf705f55e1..3d6bc1496b1f 100644 --- a/onward/app/controllers/SeriesController.scala +++ b/onward/app/controllers/SeriesController.scala @@ -32,7 +32,9 @@ class SeriesController( Action.async { implicit request => if (request.forceDCR) { lookup(Edition(request), seriesId).map { mseries => - mseries.map { series => JsonComponent(SeriesStoriesDCR.fromSeries(series)).result }.getOrElse(NotFound) + mseries + .map { series => JsonComponent.fromWritable(SeriesStoriesDCR.fromSeries(series)).result } + .getOrElse(NotFound) } } else { lookup(Edition(request), seriesId) map { series => diff --git a/onward/app/controllers/StocksController.scala b/onward/app/controllers/StocksController.scala index 5a0da6869074..f32404cd5e46 100644 --- a/onward/app/controllers/StocksController.scala +++ b/onward/app/controllers/StocksController.scala @@ -13,12 +13,12 @@ class StocksController(stocksData: StocksData, val controllerComponents: Control Action { implicit request => // Decommissioned, see marker: 7dde429f00b1 if (false && StocksWidgetSwitch.isSwitchedOff) { - Cached(1.minute)(JsonComponent(Stocks(Seq.empty))) + Cached(1.minute)(JsonComponent.fromWritable(Stocks(Seq.empty))) } else { stocksData.get match { case None => InternalServerError("Business data not loaded") case Some(stocks) => - Cached(1.minute)(JsonComponent(stocks)) + Cached(1.minute)(JsonComponent.fromWritable(stocks)) } } } diff --git a/onward/app/controllers/StoryPackageController.scala b/onward/app/controllers/StoryPackageController.scala index b911dbb14ff8..3a0bbad94ef6 100644 --- a/onward/app/controllers/StoryPackageController.scala +++ b/onward/app/controllers/StoryPackageController.scala @@ -30,7 +30,7 @@ class StoryPackageController(val contentApiClient: ContentApiClient, val control def render(path: String): Action[AnyContent] = Action.async { implicit request => getRelatedContent(path).map(items => { - val json = JsonComponent( + val json = JsonComponent.fromWritable( OnwardCollectionResponse( heading = "More on this story", trails = items.map(_.faciaContent).map(OnwardItem.pressedContentToOnwardItem).take(10), diff --git a/onward/app/weather/controllers/LocationsController.scala b/onward/app/weather/controllers/LocationsController.scala index 0e3e87ff5c2b..cd317e806070 100644 --- a/onward/app/weather/controllers/LocationsController.scala +++ b/onward/app/weather/controllers/LocationsController.scala @@ -18,7 +18,7 @@ class LocationsController(weatherApi: WeatherApi, val controllerComponents: Cont def findCity(query: String): Action[AnyContent] = Action.async { implicit request => weatherApi.searchForLocations(query) map { locations => - Cached(7.days)(JsonComponent(CityResponse.fromLocationResponses(locations.toList))) + Cached(7.days)(JsonComponent.fromWritable(CityResponse.fromLocationResponses(locations.toList))) } } @@ -58,7 +58,7 @@ class LocationsController(weatherApi: WeatherApi, val controllerComponents: Cont // We do this as AccuWeather writes "New York, New York" if no region is specified, where as we // just get "New York" from Fastly. val weatherCityWithoutRegion = weatherCity.copy(city = city) - Cached(1 hour)(JsonComponent(weatherCityWithoutRegion)) + Cached(1 hour)(JsonComponent.fromWritable(weatherCityWithoutRegion)) } } @@ -67,7 +67,7 @@ class LocationsController(weatherApi: WeatherApi, val controllerComponents: Cont cityFromRequestEdition.fold { Cached(CacheTime.NotFound)(JsonNotFound()) } { city => - Cached(1 hour)(JsonComponent(city)) + Cached(1 hour)(JsonComponent.fromWritable(city)) }, ) } diff --git a/sport/app/football/controllers/MatchController.scala b/sport/app/football/controllers/MatchController.scala index 088a8ef1bd6f..318650e24445 100644 --- a/sport/app/football/controllers/MatchController.scala +++ b/sport/app/football/controllers/MatchController.scala @@ -170,7 +170,7 @@ class MatchController( page map { page => if (request.forceDCR) { Cached(30) { - JsonComponent(Json.toJson(NsAnswer.makeFromFootballMatch(theMatch, page.lineUp))) + JsonComponent.fromWritable(NsAnswer.makeFromFootballMatch(theMatch, page.lineUp)) } } else { val htmlResponse = () => diff --git a/sport/app/football/controllers/MoreOnMatchController.scala b/sport/app/football/controllers/MoreOnMatchController.scala index 905a6b06b2da..f34cfb4352d8 100644 --- a/sport/app/football/controllers/MoreOnMatchController.scala +++ b/sport/app/football/controllers/MoreOnMatchController.scala @@ -268,17 +268,15 @@ class MoreOnMatchController( filtered <- related map { _ filter hasExactlyTwoTeams } } yield { Cached(if (theMatch.isLive) 10 else 300) { - JsonComponent( - Json.toJson( - NxAnswer.makeFromFootballMatch( - request, - theMatch, - filtered, - lineup, - competition, - theMatch.isResult, - theMatch.isLive, - ), + JsonComponent.fromWritable( + NxAnswer.makeFromFootballMatch( + request, + theMatch, + filtered, + lineup, + competition, + theMatch.isResult, + theMatch.isLive, ), ) }