001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package gov.nist.secauto.metaschema.databind.io.json; 007 008import com.fasterxml.jackson.core.JsonFactory; 009import com.fasterxml.jackson.core.JsonGenerator; 010import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; 011 012import gov.nist.secauto.metaschema.core.configuration.IMutableConfiguration; 013import gov.nist.secauto.metaschema.core.model.IBoundObject; 014import gov.nist.secauto.metaschema.core.util.ObjectUtils; 015import gov.nist.secauto.metaschema.databind.io.AbstractSerializer; 016import gov.nist.secauto.metaschema.databind.io.SerializationFeature; 017import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly; 018 019import java.io.IOException; 020import java.io.Writer; 021 022import edu.umd.cs.findbugs.annotations.NonNull; 023import nl.talsmasoftware.lazy4j.Lazy; 024 025public class DefaultJsonSerializer<CLASS extends IBoundObject> 026 extends AbstractSerializer<CLASS> { 027 private Lazy<JsonFactory> factory; 028 029 /** 030 * Construct a new Module binding-based deserializer that reads JSON-based 031 * Module content. 032 * 033 * @param definition 034 * the assembly class binding describing the Java objects this 035 * deserializer parses data into 036 */ 037 public DefaultJsonSerializer(@NonNull IBoundDefinitionModelAssembly definition) { 038 super(definition); 039 resetFactory(); 040 } 041 042 protected final void resetFactory() { 043 this.factory = Lazy.lazy(this::newFactoryInstance); 044 } 045 046 @Override 047 protected void configurationChanged(IMutableConfiguration<SerializationFeature<?>> config) { 048 super.configurationChanged(config); 049 resetFactory(); 050 } 051 052 /** 053 * Constructs a new JSON factory. 054 * <p> 055 * Subclasses can override this method to create a JSON factory with a specific 056 * configuration. 057 * 058 * @return the factory 059 */ 060 @NonNull 061 protected JsonFactory newFactoryInstance() { 062 return JsonFactoryFactory.instance(); 063 } 064 065 @NonNull 066 private JsonFactory getJsonFactory() { 067 return ObjectUtils.notNull(factory.get()); 068 } 069 070 @SuppressWarnings("resource") 071 @NonNull 072 private JsonGenerator newJsonGenerator(@NonNull Writer writer) throws IOException { 073 JsonFactory factory = getJsonFactory(); 074 return ObjectUtils.notNull(factory.createGenerator(writer) 075 .setPrettyPrinter(new DefaultPrettyPrinter())); 076 } 077 078 @Override 079 public void serialize(IBoundObject data, Writer writer) throws IOException { 080 try (JsonGenerator generator = newJsonGenerator(writer)) { 081 IBoundDefinitionModelAssembly definition = getDefinition(); 082 083 boolean serializeRoot = get(SerializationFeature.SERIALIZE_ROOT); 084 if (serializeRoot) { 085 // first write the initial START_OBJECT 086 generator.writeStartObject(); 087 088 generator.writeFieldName(definition.getRootJsonName()); 089 } 090 091 MetaschemaJsonWriter jsonWriter = new MetaschemaJsonWriter(generator); 092 jsonWriter.write(definition, data); 093 094 if (serializeRoot) { 095 generator.writeEndObject(); 096 } 097 } 098 } 099}