diff --git a/applications/app/controllers/CrosswordsController.scala b/applications/app/controllers/CrosswordsController.scala index dbbe78e15f30..d7808690e630 100644 --- a/applications/app/controllers/CrosswordsController.scala +++ b/applications/app/controllers/CrosswordsController.scala @@ -30,6 +30,7 @@ import org.joda.time.{DateTime, LocalDate} import pages.{CrosswordHtmlPage, IndexHtmlPage, PrintableCrosswordHtmlPage} import play.api.data.Forms._ import play.api.data._ +import play.api.libs.json.JsValue import play.api.libs.ws.WSClient import play.api.mvc._ import renderers.DotcomRenderingService @@ -124,7 +125,7 @@ class CrosswordPageController( } private def getDCRJson(crosswordPage: CrosswordPageWithContent, pageType: PageType)(implicit request: RequestHeader, - ): String = + ): JsValue = DotcomRenderingDataModel.toJson( DotcomRenderingDataModel.forCrossword(crosswordPage, request, pageType), ) diff --git a/applications/app/controllers/GalleryController.scala b/applications/app/controllers/GalleryController.scala index fc749a3ab4aa..65fa2b76e6c3 100644 --- a/applications/app/controllers/GalleryController.scala +++ b/applications/app/controllers/GalleryController.scala @@ -7,6 +7,7 @@ import contentapi.ContentApiClient import model._ import model.dotcomrendering.{DotcomRenderingDataModel, PageType} import pages.GalleryHtmlPage +import play.api.libs.json.JsValue import play.api.libs.ws.WSClient import play.api.mvc._ import play.twirl.api.Html @@ -74,7 +75,7 @@ class GalleryController( private def getDCRJson(galleryPage: GalleryPage, pageType: PageType, blocks: Blocks)(implicit request: RequestHeader, - ): String = { + ): JsValue = { DotcomRenderingDataModel.toJson(DotcomRenderingDataModel.forGallery(galleryPage, request, pageType, blocks)) } diff --git a/applications/app/controllers/ImageContentController.scala b/applications/app/controllers/ImageContentController.scala index daa7310efcf9..278104e22461 100644 --- a/applications/app/controllers/ImageContentController.scala +++ b/applications/app/controllers/ImageContentController.scala @@ -61,7 +61,7 @@ class ImageContentController( private def getDCRJson(content: ImageContentPage, pageType: PageType, mainBlock: Option[Block])(implicit request: RequestHeader, - ): String = { + ): JsValue = { DotcomRenderingDataModel.toJson(DotcomRenderingDataModel.forImageContent(content, request, pageType, mainBlock)) } diff --git a/applications/app/controllers/MediaController.scala b/applications/app/controllers/MediaController.scala index 6d455b3af789..2e096897844f 100644 --- a/applications/app/controllers/MediaController.scala +++ b/applications/app/controllers/MediaController.scala @@ -9,7 +9,7 @@ import implicits.{AppsFormat, JsonFormat} import model._ import model.dotcomrendering.{DotcomRenderingDataModel, PageType} import pages.ContentHtmlPage -import play.api.libs.json.{Format, JsObject, Json} +import play.api.libs.json.{Format, JsObject, Json, JsValue} import play.api.libs.ws.WSClient import play.api.mvc._ import renderers.DotcomRenderingService @@ -96,7 +96,7 @@ class MediaController( private def getDCRJson(content: MediaPage, pageType: PageType, blocks: Blocks)(implicit request: RequestHeader, - ): String = { + ): JsValue = { DotcomRenderingDataModel.toJson(DotcomRenderingDataModel.forMedia(content, request, pageType, blocks)) } diff --git a/article/app/controllers/ArticleController.scala b/article/app/controllers/ArticleController.scala index 1ea08a3eb076..6ac328f52364 100644 --- a/article/app/controllers/ArticleController.scala +++ b/article/app/controllers/ArticleController.scala @@ -8,7 +8,7 @@ import model.Cached.{RevalidatableResult, WithoutRevalidationResult} import model.dotcomrendering.{DotcomRenderingDataModel, PageType} import model._ import pages.{ArticleEmailHtmlPage, ArticleHtmlPage} -import play.api.libs.json.Json +import play.api.libs.json.{Json, JsValue} import play.api.libs.ws.WSClient import play.api.mvc._ import renderers.DotcomRenderingService @@ -91,7 +91,7 @@ class ArticleController( /** Returns a JSON representation of the payload that's sent to DCR when rendering the Article. */ - private def getDCRJson(article: ArticlePage, blocks: Blocks)(implicit request: RequestHeader): String = { + private def getDCRJson(article: ArticlePage, blocks: Blocks)(implicit request: RequestHeader): JsValue = { val pageType: PageType = PageType(article, request, context) val newsletter = newsletterService.getNewsletterForArticle(article) diff --git a/common/app/common/package.scala b/common/app/common/package.scala index 51f51aeb4341..dc4ea81434e4 100644 --- a/common/app/common/package.scala +++ b/common/app/common/package.scala @@ -10,7 +10,7 @@ import model.CacheTime.RecentlyUpdated import model.Cached.RevalidatableResult import model.{ApplicationContext, Cached, NoCache} import play.api.Logger -import play.api.libs.json.{JsObject, JsString} +import play.api.libs.json.{JsObject, JsString, JsValue} import play.api.mvc.{RequestHeader, Result} import play.twirl.api.Html import model.ApplicationContext @@ -162,7 +162,10 @@ object `package` JsonComponent(page, json) } - def renderJson(json: String, page: model.Page)(implicit request: RequestHeader, context: ApplicationContext): Result = + def renderJson(json: JsValue, page: model.Page)(implicit + request: RequestHeader, + context: ApplicationContext, + ): Result = Cached(page) { RevalidatableResult.Ok(json) } diff --git a/common/app/model/dotcomrendering/DotcomBlocksRenderingDataModel.scala b/common/app/model/dotcomrendering/DotcomBlocksRenderingDataModel.scala index 6edc08e8aa59..edba663ef04a 100644 --- a/common/app/model/dotcomrendering/DotcomBlocksRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/DotcomBlocksRenderingDataModel.scala @@ -58,9 +58,9 @@ object DotcomBlocksRenderingDataModel { } } - def toJson(model: DotcomBlocksRenderingDataModel): String = { + def toJson(model: DotcomBlocksRenderingDataModel): JsValue = { val jsValue = Json.toJson(model) - Json.stringify(DotcomRenderingUtils.withoutNull(jsValue)) + DotcomRenderingUtils.withoutNull(jsValue) } def apply( diff --git a/common/app/model/dotcomrendering/DotcomFrontsRenderingDataModel.scala b/common/app/model/dotcomrendering/DotcomFrontsRenderingDataModel.scala index dbec33a6051b..d5fc57c7206d 100644 --- a/common/app/model/dotcomrendering/DotcomFrontsRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/DotcomFrontsRenderingDataModel.scala @@ -98,8 +98,8 @@ object DotcomFrontsRenderingDataModel { ) } - def toJson(model: DotcomFrontsRenderingDataModel): String = { + def toJson(model: DotcomFrontsRenderingDataModel): JsValue = { val jsValue = Json.toJson(model) - Json.stringify(DotcomRenderingUtils.withoutNull(jsValue)) + DotcomRenderingUtils.withoutNull(jsValue) } } diff --git a/common/app/model/dotcomrendering/DotcomNewslettersPageRenderingDataModel.scala b/common/app/model/dotcomrendering/DotcomNewslettersPageRenderingDataModel.scala index 0754e2159071..46256ce4ddae 100644 --- a/common/app/model/dotcomrendering/DotcomNewslettersPageRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/DotcomNewslettersPageRenderingDataModel.scala @@ -97,9 +97,9 @@ object DotcomNewslettersPageRenderingDataModel { ) } - def toJson(model: DotcomNewslettersPageRenderingDataModel): String = { + def toJson(model: DotcomNewslettersPageRenderingDataModel): JsValue = { val jsValue = Json.toJson(model) - Json.stringify(DotcomRenderingUtils.withoutNull(jsValue)) + DotcomRenderingUtils.withoutNull(jsValue) } private def convertNewsletterResponseToData(response: NewsletterResponseV2): NewsletterData = { diff --git a/common/app/model/dotcomrendering/DotcomRenderingDataModel.scala b/common/app/model/dotcomrendering/DotcomRenderingDataModel.scala index b8771ad55e77..cce1327fef43 100644 --- a/common/app/model/dotcomrendering/DotcomRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/DotcomRenderingDataModel.scala @@ -191,9 +191,9 @@ object DotcomRenderingDataModel { } } - def toJson(model: DotcomRenderingDataModel): String = { + def toJson(model: DotcomRenderingDataModel): JsValue = { val jsValue = Json.toJson(model) - Json.stringify(withoutNull(jsValue)) + withoutNull(jsValue) } def forInteractive( diff --git a/common/app/model/dotcomrendering/DotcomTagPagesRenderingDataModel.scala b/common/app/model/dotcomrendering/DotcomTagPagesRenderingDataModel.scala index 4a76a7bf9761..2cf5dc72cf7d 100644 --- a/common/app/model/dotcomrendering/DotcomTagPagesRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/DotcomTagPagesRenderingDataModel.scala @@ -132,8 +132,8 @@ object DotcomTagPagesRenderingDataModel { ) } - def toJson(model: DotcomTagPagesRenderingDataModel): String = { + def toJson(model: DotcomTagPagesRenderingDataModel): JsValue = { val jsValue = Json.toJson(model) - Json.stringify(DotcomRenderingUtils.withoutNull(jsValue)) + DotcomRenderingUtils.withoutNull(jsValue) } } diff --git a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala index 180e91803acd..3b6c92c1d835 100644 --- a/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala +++ b/common/app/model/dotcomrendering/pageElements/EditionsCrosswordRenderingDataModel.scala @@ -2,9 +2,10 @@ package model.dotcomrendering.pageElements import com.gu.contentapi.client.model.v1.Crossword import com.gu.contentapi.json.CirceEncoders._ -import io.circe.JsonObject import io.circe.syntax._ import implicits.Dates.CapiRichDateTime +import model.dotcomrendering.DotcomRenderingUtils +import play.api.libs.json.{JsObject, Json, JsValue} case class EditionsCrosswordRenderingDataModel( crosswords: Iterable[Crossword], @@ -25,9 +26,10 @@ object EditionsCrosswordRenderingDataModel { } })) - def toJson(model: EditionsCrosswordRenderingDataModel): String = { - JsonObject( - "crosswords" -> model.crosswords.asJson.deepDropNullValues, - ).asJson.noSpaces - } + def toJson(model: EditionsCrosswordRenderingDataModel): JsValue = + DotcomRenderingUtils.withoutNull( + Json.obj( + "crosswords" -> Json.parse(model.crosswords.asJson.toString()), + ), + ) } diff --git a/common/app/renderers/DotcomRenderingService.scala b/common/app/renderers/DotcomRenderingService.scala index 32d7e067a59a..14d2ed7c87d3 100644 --- a/common/app/renderers/DotcomRenderingService.scala +++ b/common/app/renderers/DotcomRenderingService.scala @@ -25,6 +25,7 @@ import model.{ RelatedContentItem, SimplePage, } +import play.api.libs.json.JsValue import play.api.libs.ws.{WSClient, WSResponse} import play.api.mvc.Results.{InternalServerError, NotFound} import play.api.mvc.{RequestHeader, Result} @@ -56,7 +57,7 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload private[this] def postWithoutHandler( ws: WSClient, - payload: String, + payload: JsValue, endpoint: String, timeout: Duration = Configuration.rendering.timeout, )(implicit request: RequestHeader): Future[WSResponse] = { @@ -93,7 +94,7 @@ class DotcomRenderingService extends GuLogging with ResultWithPreconnectPreload private[this] def post( ws: WSClient, - payload: String, + payload: JsValue, endpoint: String, cacheTime: CacheTime, timeout: Duration = Configuration.rendering.timeout, diff --git a/common/test/renderers/DotcomRenderingServiceTest.scala b/common/test/renderers/DotcomRenderingServiceTest.scala index 7e3d2f4477c9..6f4fd2158cbe 100644 --- a/common/test/renderers/DotcomRenderingServiceTest.scala +++ b/common/test/renderers/DotcomRenderingServiceTest.scala @@ -6,6 +6,7 @@ import org.scalatest.{BeforeAndAfterAll, DoNotDiscover, PrivateMethodTester} import org.scalatest.matchers.should.Matchers import test.{ConfiguredTestSuite, TestRequest, WithMaterializer, WithTestWsClient} import play.api.libs.ws.{WSClient, WSRequest, WSResponse} +import play.api.libs.json.{JsString} import play.api.mvc.{Result} import conf.Configuration import org.mockito.Matchers.any @@ -35,7 +36,7 @@ import org.scalatest.flatspec.AnyFlatSpec private val wsRequestMock = mock[WSRequest] "post" should "return a 404 for DCR 415 errors" in { - val payload = "payload" + val payload = JsString("payload") when(wsMock.url(any[String])).thenReturn(wsRequestMock) when(wsRequestMock.withRequestTimeout(any())).thenReturn(wsRequestMock) when(wsRequestMock.addHttpHeaders(any())).thenReturn(wsRequestMock)