package com.psddev.cms.view; import com.psddev.dari.util.ObjectUtils; import java.util.LinkedHashMap; import java.util.Map; /** * Renderer that converts the views to JSON. */ public class JsonViewRenderer implements ViewRenderer { private boolean includeClassNames; private boolean indented; private boolean disallowMixedOutput; /** * @return true if class names should be included in the output in the * "class" key, false otherwise. */ public boolean isIncludeClassNames() { return includeClassNames; } /** * Sets whether class names should be included in the output in the "class" * key. * * @param includeClassNames true if class names should be included. */ public void setIncludeClassNames(boolean includeClassNames) { this.includeClassNames = includeClassNames; } /** * @return true if the output should be indented, false otherwise. */ public boolean isIndented() { return indented; } /** * Sets whether the output should be indented or not. * * @param indented true if the output should be indented. */ public void setIndented(boolean indented) { this.indented = indented; } /** * @return true if the view and all its sub-views should be rendered as * JSON even if they have a different view renderer, */ public boolean isDisallowMixedOutput() { return disallowMixedOutput; } /** * Sets whether the output format should be mixed or not. * * @param disallowMixedOutput true if mixed output should be disallowed. */ public void setDisallowMixedOutput(boolean disallowMixedOutput) { this.disallowMixedOutput = disallowMixedOutput; } @Override public String getContentType() { return "application/json"; } @Deprecated @Override public ViewOutput render(Object view) { return render(view, null); } @Override public ViewOutput render(Object view, ViewTemplateLoader loader) { return () -> ObjectUtils.toJson(getRenderableMap(view, loader), indented); } // Gets the final map that is passed to ObjectUtils#toJson private Map<String, Object> getRenderableMap(Object view, ViewTemplateLoader loader) { Map<String, Object> viewMap; if (view instanceof Map) { viewMap = (Map<String, Object>) view; } else { viewMap = new ViewMap(view, includeClassNames); } if (disallowMixedOutput) { return viewMap; } Map<String, Object> jsonMap = new LinkedHashMap<>(); for (Map.Entry<?, ?> entry : viewMap.entrySet()) { String key = String.valueOf(entry.getKey()); Object value = entry.getValue(); ViewRenderer renderer = ViewRenderer.createRenderer(value); if (renderer != null) { if (renderer instanceof JsonViewRenderer) { jsonMap.put(key, ((JsonViewRenderer) renderer).getRenderableMap(value, loader)); } else { Object renderedValue = null; ViewOutput viewOutput = renderer.render(value, loader); if (viewOutput != null) { String output = viewOutput.get(); if (output != null) { try { renderedValue = ObjectUtils.fromJson(output); } catch (RuntimeException e) { renderedValue = output; } } } jsonMap.put(key, renderedValue); } } else { jsonMap.put(key, value); } } return jsonMap; } }