![JAR search and dependency download from the Maven repository](/logo.png)
com.exactpro.sf.services.json.JSONVisitorDecode Maven / Gradle / Ivy
/******************************************************************************
* Copyright 2009-2023 Exactpro (Exactpro Systems Limited)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.exactpro.sf.services.json;
import static com.exactpro.sf.common.messages.structures.StructureUtils.getAttributeValue;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.BooleanUtils;
import org.jetbrains.annotations.Nullable;
import com.exactpro.sf.common.messages.DefaultMessageStructureVisitor;
import com.exactpro.sf.common.messages.IMessage;
import com.exactpro.sf.common.messages.IMessageFactory;
import com.exactpro.sf.common.messages.IMessageStructureVisitor;
import com.exactpro.sf.common.messages.MessageStructureWriter;
import com.exactpro.sf.common.messages.structures.IFieldStructure;
import com.exactpro.sf.common.messages.structures.StructureUtils;
import com.exactpro.sf.common.util.EPSCommonException;
import com.exactpro.sf.util.DateTimeUtility;
import com.fasterxml.jackson.databind.JsonNode;
public class JSONVisitorDecode extends DefaultMessageStructureVisitor {
private final JsonNode rootNode;
private final IMessageFactory msgFactory;
private final IMessage result;
private final JsonSettings jsonSettings;
public JSONVisitorDecode(JsonNode rootNode, IMessageFactory msgFactory, IMessage message, JsonSettings jsonSettings) {
this.rootNode = rootNode;
this.msgFactory = msgFactory;
this.result = message;
this.jsonSettings = jsonSettings;
}
@Override
public void visit(String fieldName, Byte value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? (byte)Integer.parseInt(valueNode.asText()): (byte)valueNode.asInt();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Short value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? (short)Integer.parseInt(valueNode.asText()): (short)valueNode.asInt();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Integer value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? Integer.parseInt(valueNode.asText()): valueNode.asInt();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Long value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? Long.parseLong(valueNode.asText()): valueNode.asLong();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, BigDecimal value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? new BigDecimal(valueNode.asText()): valueNode.decimalValue();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Boolean value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? Boolean.parseBoolean(valueNode.asText()): valueNode.asBoolean();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Character value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
if (valueNode.asText().length() > 1) {
//TODO edit ex message
throw new EPSCommonException("overflow");
}
value = valueNode.asText().charAt(0);
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, LocalDateTime value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
if (JSONVisitorUtility.ISO_UTC_FORMAT.equals(getAttributeValue(fldStruct, JSONVisitorUtility.FORMAT_ATTRIBUTE))) {
value = LocalDateTime.parse(valueNode.asText(), JSONVisitorUtility.FORMATTER);
} else {
value = DateTimeUtility.toLocalDateTime(ZonedDateTime.parse(valueNode.asText()));
}
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, String value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
value = valueNode.asText();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Double value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? Double.parseDouble(valueNode.asText()): valueNode.asDouble();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, Float value, IFieldStructure fldStruct, boolean isDefault) {
JsonNode valueNode = getJsonNode(fldStruct, rootNode);
if(valueNode == null) return;
if(addIfNull(result, fieldName, valueNode)) return;
//TODO overflow check
value = jsonSettings.isTreatSimpleValuesAsStrings() ? Float.parseFloat(valueNode.asText()): (float)valueNode.asDouble();
result.addField(fieldName, value);
}
@Override
public void visit(String fieldName, IMessage message, IFieldStructure fldStruct, boolean isDefault) {
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
if(!rootNode.has(jsonFieldName)) return;
JsonNode valueNode = rootNode.path(jsonFieldName);
if(addIfNull(result, fieldName, valueNode)) return;
JsonNode node = JSONVisitorUtility.preprocessMessageNode(this.rootNode.get(jsonFieldName), fldStruct);
IMessage nested = msgFactory.createMessage(fldStruct.getReferenceName(), fldStruct.getNamespace());
IMessageStructureVisitor jsonVisitorDecode = new JSONVisitorDecode(node, msgFactory, nested, jsonSettings);
MessageStructureWriter.WRITER.traverse(jsonVisitorDecode, fldStruct.getFields());
if (jsonSettings.isRejectUnexpectedFields()) {
String rejectReason = JSONVisitorUtility.checkForUnexpectedFields(node, fldStruct);
JSONVisitorUtility.addRejectReason(nested, rejectReason);
JSONVisitorUtility.addRejectReason(result, nested.getMetaData().getRejectReason());
}
result.addField(fieldName, nested);
}
@Override
public void visitByteCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? (byte)Integer.parseInt(element.asText()) : (byte)element.asInt());
}
result.addField(fieldName, list);
}
}
@Override
public void visitShortCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? (short)Integer.parseInt(element.asText()) : (short)element.asInt());
}
result.addField(fieldName, list);
}
}
@Override
public void visitIntCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? Integer.parseInt(element.asText()) : element.asInt());
}
result.addField(fieldName, list);
}
}
@Override
public void visitLongCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? Long.parseLong(element.asText()) : element.asLong());
}
result.addField(fieldName, list);
}
}
@Override
public void visitBigDecimalCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) return;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? new BigDecimal(element.asText()) : element.decimalValue());
}
result.addField(fieldName, list);
}
}
@Override
public void visitCharCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
if (element.asText().length() == 1) {
list.add(element.asText().charAt(0));
}
}
result.addField(fieldName, list);
}
}
@Override
public void visitStringCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(element.asText());
}
result.addField(fieldName, list);
}
}
@Override
public void visitBooleanCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? Boolean.parseBoolean(element.asText()) : element.asBoolean());
}
result.addField(fieldName, list);
}
}
@Override
public void visitDateTimeCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
SimpleDateFormat dateFormat = new SimpleDateFormat();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
try {
list.add(DateTimeUtility.toLocalDateTime(dateFormat.parse(element.asText())));
} catch (ParseException e) {
//TODO throw ex normally
throw new EPSCommonException(e);
}
}
result.addField(fieldName, list);
}
}
@Override
public void visitDoubleCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? Double.parseDouble(element.asText()) : element.asDouble());
}
result.addField(fieldName, list);
}
}
@Override
public void visitFloatCollection(String fieldName, List value, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
Iterator valueNodes = getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = valueNodes.next();
if(addIfNull(list, fieldName, element)) continue;
list.add(jsonSettings.isTreatSimpleValuesAsStrings() ? Float.parseFloat(element.asText()) : (float)element.asDouble());
}
result.addField(fieldName, list);
}
}
@Override
public void visitMessageCollection(String fieldName, List message, IFieldStructure fldStruct, boolean isDefault) {
if(addIfNullList(result, fldStruct, rootNode)) return;
boolean keyValueList = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(fldStruct, JSONMessageHelper.KEY_VALUE_LIST_ATTR));
Iterator valueNodes = keyValueList
? getKeyValueList(fldStruct, rootNode)
: getJsonNodes(fldStruct, rootNode);
if (valueNodes != null) {
List list = new ArrayList<>();
while (valueNodes.hasNext()) {
JsonNode element = JSONVisitorUtility.preprocessMessageNode(valueNodes.next(), fldStruct);
if(addIfNull(list, fieldName, element)) continue;
IMessage nested = msgFactory.createMessage(fldStruct.getReferenceName(), fldStruct.getNamespace());
IMessageStructureVisitor jsonVisitorDecode = new JSONVisitorDecode(element, msgFactory, nested, jsonSettings);
MessageStructureWriter.WRITER.traverse(jsonVisitorDecode, fldStruct.getFields());
if (jsonSettings.isRejectUnexpectedFields()) {
String rejectReason = JSONVisitorUtility.checkForUnexpectedFields(element, fldStruct);
JSONVisitorUtility.addRejectReason(nested, rejectReason);
JSONVisitorUtility.addRejectReason(result, nested.getMetaData().getRejectReason());
}
list.add(nested);
}
result.addField(fieldName, list);
}
}
public static JsonNode getJsonNode(IFieldStructure fldStruct, JsonNode rootNode) {
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
return rootNode.has(jsonFieldName) ? rootNode.path(jsonFieldName) : null;
}
@Nullable
public static Iterator getJsonNodes(IFieldStructure fldStruct, JsonNode rootNode) {
boolean isNoName = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(fldStruct, JSONMessageHelper.IS_NO_NAME_ATTR));
if (isNoName) {
return rootNode.isArray() ? rootNode.elements() : null;
}
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
if (rootNode.hasNonNull(jsonFieldName)) {
JsonNode node = rootNode.path(jsonFieldName);
return node.isArray() ? node.elements() : null;
}
return null;
}
@Nullable
public static Iterator getKeyValueList(IFieldStructure fldStruct, JsonNode rootNode) {
boolean isNoName = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(fldStruct, JSONMessageHelper.IS_NO_NAME_ATTR));
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
if (rootNode.hasNonNull(jsonFieldName)) {
JsonNode node = rootNode.path(jsonFieldName);
return JSONVisitorUtility.convertToKeyValueList(fldStruct.getName(), node).iterator();
}
return null;
}
private static Boolean addIfNull(IMessage message, String fieldName, JsonNode valueNode) {
if(valueNode.isNull()) {
message.addField(fieldName, null);
return true;
}
return false;
}
private static Boolean addIfNull(List array, String fieldName, JsonNode valueNode) {
if(valueNode.isNull()) {
array.add(null);
return true;
}
return false;
}
private static Boolean addIfNullList(IMessage message, IFieldStructure fldStruct, JsonNode rootNode) {
boolean isNoName = BooleanUtils.toBoolean(StructureUtils.getAttributeValue(fldStruct, JSONMessageHelper.IS_NO_NAME_ATTR));
if (isNoName) return false;
String jsonFieldName = JSONVisitorUtility.getJsonFieldName(fldStruct);
if(!rootNode.has(jsonFieldName)) return true;
JsonNode valueNode = rootNode.path(jsonFieldName);
return addIfNull(message, fldStruct.getName(), valueNode);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy