Search in sources :

Example 1 with JsonStringExt

use of com.linkedin.avroutil1.parser.jsonpext.JsonStringExt in project avro-util by linkedin.

the class AvscParser method parseSimplePrimitiveOrRef.

private SchemaOrRef parseSimplePrimitiveOrRef(JsonStringExt stringNode, AvscFileParseContext context) {
    CodeLocation codeLocation = locationOf(context.getUri(), stringNode);
    String typeString = stringNode.getString();
    AvroType avroType = AvroType.fromJson(typeString);
    // TODO - screen for reserved words??
    if (avroType == null) {
        // assume it's a ref
        return new SchemaOrRef(codeLocation, typeString);
    }
    if (avroType.isPrimitive()) {
        // no logical type information, string representation or props in the schema if we got here
        return new SchemaOrRef(codeLocation, AvroPrimitiveSchema.forType(codeLocation, avroType, null, null, 0, 0, JsonPropertiesContainer.EMPTY));
    }
    // if we got here it means we found something like "record" as a type literal. which is not valid syntax
    throw new AvroSyntaxException("Illegal avro type \"" + typeString + "\" at " + codeLocation.getStart() + ". " + "Expecting a primitive type, an inline type definition or a reference the the fullname of a named type defined elsewhere");
}
Also used : CodeLocation(com.linkedin.avroutil1.model.CodeLocation) SchemaOrRef(com.linkedin.avroutil1.model.SchemaOrRef) AvroType(com.linkedin.avroutil1.model.AvroType) AvroSyntaxException(com.linkedin.avroutil1.parser.exceptions.AvroSyntaxException)

Example 2 with JsonStringExt

use of com.linkedin.avroutil1.parser.jsonpext.JsonStringExt in project avro-util by linkedin.

the class AvscParser method getOptionalString.

private Located<String> getOptionalString(JsonObjectExt node, String prop) {
    JsonValueExt val = node.get(prop);
    if (val == null) {
        return null;
    }
    JsonValue.ValueType valType = val.getValueType();
    if (valType != JsonValue.ValueType.STRING) {
        throw new AvroSyntaxException("\"" + prop + "\" property at " + val.getStartLocation() + " is expected to be a string, not a " + JsonPUtil.describe(valType) + " (" + val + ")");
    }
    return new Located<>(((JsonStringExt) val).getString(), Util.convertLocation(val.getStartLocation()));
}
Also used : AvroSyntaxException(com.linkedin.avroutil1.parser.exceptions.AvroSyntaxException) Located(com.linkedin.avroutil1.parser.Located) JsonValue(jakarta.json.JsonValue) JsonValueExt(com.linkedin.avroutil1.parser.jsonpext.JsonValueExt)

Example 3 with JsonStringExt

use of com.linkedin.avroutil1.parser.jsonpext.JsonStringExt in project avro-util by linkedin.

the class AvscParser method parseLiteral.

private LiteralOrIssue parseLiteral(JsonValueExt literalNode, AvroSchema schema, String fieldName, AvscFileParseContext context) {
    AvroType avroType = schema.type();
    JsonValue.ValueType jsonType = literalNode.getValueType();
    AvscIssue issue;
    BigInteger bigIntegerValue;
    BigDecimal bigDecimalValue;
    byte[] bytes;
    switch(avroType) {
        case NULL:
            if (jsonType != JsonValue.ValueType.NULL) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroNullLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode)));
        case BOOLEAN:
            if (jsonType != JsonValue.ValueType.FALSE && jsonType != JsonValue.ValueType.TRUE) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            boolean boolValue = jsonType == JsonValue.ValueType.TRUE;
            return new LiteralOrIssue(new AvroBooleanLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), boolValue));
        case INT:
            if (jsonType != JsonValue.ValueType.NUMBER) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            JsonNumberExt intNode = (JsonNumberExt) literalNode;
            if (!intNode.isIntegral()) {
                // TODO - be more specific about this error (int vs float)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            bigIntegerValue = intNode.bigIntegerValue();
            if (bigIntegerValue.compareTo(MAX_INT) > 0 || bigIntegerValue.compareTo(MIN_INT) < 0) {
                // TODO - be more specific about this error (out of signed int range)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroIntegerLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), bigIntegerValue.intValueExact()));
        case LONG:
            if (jsonType != JsonValue.ValueType.NUMBER) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            JsonNumberExt longNode = (JsonNumberExt) literalNode;
            if (!longNode.isIntegral()) {
                // TODO - be more specific about this error (long vs float)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            bigIntegerValue = longNode.bigIntegerValue();
            if (bigIntegerValue.compareTo(MAX_LONG) > 0 || bigIntegerValue.compareTo(MIN_LONG) < 0) {
                // TODO - be more specific about this error (out of signed long range)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroLongLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), bigIntegerValue.longValueExact()));
        case FLOAT:
            if (jsonType != JsonValue.ValueType.NUMBER) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            JsonNumberExt floatNode = (JsonNumberExt) literalNode;
            bigDecimalValue = floatNode.bigDecimalValue();
            if (bigDecimalValue.compareTo(MAX_FLOAT) > 0) {
                // TODO - be more specific about this error (out of float range)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroFloatLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), bigDecimalValue.floatValue()));
        case DOUBLE:
            if (jsonType != JsonValue.ValueType.NUMBER) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            JsonNumberExt doubleNode = (JsonNumberExt) literalNode;
            bigDecimalValue = doubleNode.bigDecimalValue();
            if (bigDecimalValue.compareTo(MAX_DOUBLE) > 0) {
                // TODO - be more specific about this error (out of double range)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroDoubleLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), bigDecimalValue.doubleValue()));
        case BYTES:
            if (jsonType != JsonValue.ValueType.STRING) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            JsonStringExt bytesNode = (JsonStringExt) literalNode;
            // spec says "strings, where Unicode code points 0-255 are mapped to unsigned 8-bit byte values 0-255"
            bytes = bytesNode.getString().getBytes(StandardCharsets.ISO_8859_1);
            return new LiteralOrIssue(new AvroBytesLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), bytes));
        case FIXED:
            if (jsonType != JsonValue.ValueType.STRING) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            AvroFixedSchema fixedSchema = (AvroFixedSchema) schema;
            JsonStringExt fixedNode = (JsonStringExt) literalNode;
            // spec says "strings, where Unicode code points 0-255 are mapped to unsigned 8-bit byte values 0-255"
            bytes = fixedNode.getString().getBytes(StandardCharsets.ISO_8859_1);
            if (bytes.length != fixedSchema.getSize()) {
                // TODO - be more specific about this error (wrong length)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroFixedLiteral(fixedSchema, locationOf(context.getUri(), literalNode), bytes));
        case STRING:
            if (jsonType != JsonValue.ValueType.STRING) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            JsonStringExt stringNode = (JsonStringExt) literalNode;
            return new LiteralOrIssue(new AvroStringLiteral((AvroPrimitiveSchema) schema, locationOf(context.getUri(), literalNode), stringNode.getString()));
        case ENUM:
            if (jsonType != JsonValue.ValueType.STRING) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            AvroEnumSchema enumSchema = (AvroEnumSchema) schema;
            JsonStringExt enumNode = (JsonStringExt) literalNode;
            String enumValue = enumNode.getString();
            if (!enumSchema.getSymbols().contains(enumValue)) {
                // TODO - be more specific about this error (unknown symbol)
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            return new LiteralOrIssue(new AvroEnumLiteral(enumSchema, locationOf(context.getUri(), literalNode), enumValue));
        case ARRAY:
            if (jsonType != JsonValue.ValueType.ARRAY) {
                issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                context.addIssue(issue);
                return new LiteralOrIssue(issue);
            }
            AvroArraySchema arraySchema = (AvroArraySchema) schema;
            AvroSchema valueSchema = arraySchema.getValueSchema();
            JsonArrayExt arrayNode = (JsonArrayExt) literalNode;
            ArrayList<AvroLiteral> values = new ArrayList<>(arrayNode.size());
            for (int i = 0; i < arrayNode.size(); i++) {
                JsonValueExt valueNode = (JsonValueExt) arrayNode.get(i);
                LiteralOrIssue value = parseLiteral(valueNode, valueSchema, fieldName, context);
                // issues parsing any member value mean a failure to parse the array as a whole
                if (value.getIssue() != null) {
                    // TODO - be more specific about this error (unparsable array element i)
                    // TODO - add "causedBy" to AvscIssue and use it here
                    issue = AvscIssues.badFieldDefaultValue(locationOf(context.getUri(), literalNode), literalNode.toString(), avroType, fieldName);
                    context.addIssue(issue);
                    return new LiteralOrIssue(issue);
                }
                values.add(value.getLiteral());
            }
            return new LiteralOrIssue(new AvroArrayLiteral(arraySchema, locationOf(context.getUri(), literalNode), values));
        default:
            throw new UnsupportedOperationException("dont know how to parse a " + avroType + " at " + literalNode.getStartLocation() + " out of a " + literalNode.getValueType() + " (" + literalNode + ")");
    }
}
Also used : AvroSchema(com.linkedin.avroutil1.model.AvroSchema) AvroLongLiteral(com.linkedin.avroutil1.model.AvroLongLiteral) ArrayList(java.util.ArrayList) AvroFloatLiteral(com.linkedin.avroutil1.model.AvroFloatLiteral) AvroEnumSchema(com.linkedin.avroutil1.model.AvroEnumSchema) JsonArrayExt(com.linkedin.avroutil1.parser.jsonpext.JsonArrayExt) AvroPrimitiveSchema(com.linkedin.avroutil1.model.AvroPrimitiveSchema) AvroArraySchema(com.linkedin.avroutil1.model.AvroArraySchema) AvroArrayLiteral(com.linkedin.avroutil1.model.AvroArrayLiteral) AvroFixedLiteral(com.linkedin.avroutil1.model.AvroFixedLiteral) AvroFixedSchema(com.linkedin.avroutil1.model.AvroFixedSchema) AvroIntegerLiteral(com.linkedin.avroutil1.model.AvroIntegerLiteral) AvroBytesLiteral(com.linkedin.avroutil1.model.AvroBytesLiteral) AvroLiteral(com.linkedin.avroutil1.model.AvroLiteral) JsonNumberExt(com.linkedin.avroutil1.parser.jsonpext.JsonNumberExt) JsonStringExt(com.linkedin.avroutil1.parser.jsonpext.JsonStringExt) JsonValue(jakarta.json.JsonValue) AvroBooleanLiteral(com.linkedin.avroutil1.model.AvroBooleanLiteral) AvroStringLiteral(com.linkedin.avroutil1.model.AvroStringLiteral) BigDecimal(java.math.BigDecimal) AvroDoubleLiteral(com.linkedin.avroutil1.model.AvroDoubleLiteral) AvroNullLiteral(com.linkedin.avroutil1.model.AvroNullLiteral) AvroType(com.linkedin.avroutil1.model.AvroType) BigInteger(java.math.BigInteger) JsonValueExt(com.linkedin.avroutil1.parser.jsonpext.JsonValueExt) AvroEnumLiteral(com.linkedin.avroutil1.model.AvroEnumLiteral)

Example 4 with JsonStringExt

use of com.linkedin.avroutil1.parser.jsonpext.JsonStringExt in project avro-util by linkedin.

the class Util method convertJsonValue.

/**
 * converts json values to:
 * <ul>
 *     <li>{@link com.linkedin.avroutil1.model.JsonPropertiesContainer#NULL_VALUE} for json nulls</li>
 *     <li>Booleans for json boolean values</li>
 *     <li>BigDecimals for json numeric values</li>
 *     <li>java.lang.Strings for json strings</li>
 *     <li>
 *         java.util.List&lt;Object&gt;s for json arrays, where individual members
 *         are anything on this list.
 *     </li>
 *     <li>
 *         java.util.LinkedHashMap&lt;String,Object&gt;s for json objects, where
 *         keys are strings, values are anything on this list, and property order
 *         is preserved
 *     </li>
 * </ul>
 * @param jsonValue a json value
 * @return value converted according to the doc
 */
public static Object convertJsonValue(JsonValueExt jsonValue) {
    if (jsonValue == null) {
        throw new IllegalArgumentException("jsonValue cannot be null");
    }
    JsonValue.ValueType jsonType = jsonValue.getValueType();
    switch(jsonType) {
        case NULL:
            return JsonPropertiesContainer.NULL_VALUE;
        case TRUE:
            return Boolean.TRUE;
        case FALSE:
            return Boolean.FALSE;
        case NUMBER:
            return ((JsonNumberExt) jsonValue).bigDecimalValue();
        case STRING:
            return ((JsonStringExt) jsonValue).getString();
        case ARRAY:
            JsonArrayExt jsonArray = (JsonArrayExt) jsonValue;
            List<Object> list = new ArrayList<>(jsonArray.size());
            for (JsonValue val : jsonArray) {
                list.add(convertJsonValue((JsonValueExt) val));
            }
            return list;
        case OBJECT:
            JsonObjectExt jsonObj = (JsonObjectExt) jsonValue;
            Set<Map.Entry<String, JsonValue>> entries = jsonObj.entrySet();
            LinkedHashMap<String, Object> map = new LinkedHashMap<>(entries.size());
            for (Map.Entry<String, JsonValue> entry : entries) {
                String key = entry.getKey();
                JsonValueExt val = (JsonValueExt) entry.getValue();
                map.put(key, convertJsonValue(val));
            }
            return map;
        default:
            throw new IllegalStateException("unhandled json type " + jsonType + " for " + jsonValue + " at " + jsonValue.getStartLocation());
    }
}
Also used : JsonStringExt(com.linkedin.avroutil1.parser.jsonpext.JsonStringExt) JsonValue(jakarta.json.JsonValue) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) JsonArrayExt(com.linkedin.avroutil1.parser.jsonpext.JsonArrayExt) JsonObjectExt(com.linkedin.avroutil1.parser.jsonpext.JsonObjectExt) JsonValueExt(com.linkedin.avroutil1.parser.jsonpext.JsonValueExt) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) JsonNumberExt(com.linkedin.avroutil1.parser.jsonpext.JsonNumberExt)

Aggregations

JsonValueExt (com.linkedin.avroutil1.parser.jsonpext.JsonValueExt)3 JsonValue (jakarta.json.JsonValue)3 AvroType (com.linkedin.avroutil1.model.AvroType)2 AvroSyntaxException (com.linkedin.avroutil1.parser.exceptions.AvroSyntaxException)2 JsonArrayExt (com.linkedin.avroutil1.parser.jsonpext.JsonArrayExt)2 JsonNumberExt (com.linkedin.avroutil1.parser.jsonpext.JsonNumberExt)2 JsonStringExt (com.linkedin.avroutil1.parser.jsonpext.JsonStringExt)2 ArrayList (java.util.ArrayList)2 AvroArrayLiteral (com.linkedin.avroutil1.model.AvroArrayLiteral)1 AvroArraySchema (com.linkedin.avroutil1.model.AvroArraySchema)1 AvroBooleanLiteral (com.linkedin.avroutil1.model.AvroBooleanLiteral)1 AvroBytesLiteral (com.linkedin.avroutil1.model.AvroBytesLiteral)1 AvroDoubleLiteral (com.linkedin.avroutil1.model.AvroDoubleLiteral)1 AvroEnumLiteral (com.linkedin.avroutil1.model.AvroEnumLiteral)1 AvroEnumSchema (com.linkedin.avroutil1.model.AvroEnumSchema)1 AvroFixedLiteral (com.linkedin.avroutil1.model.AvroFixedLiteral)1 AvroFixedSchema (com.linkedin.avroutil1.model.AvroFixedSchema)1 AvroFloatLiteral (com.linkedin.avroutil1.model.AvroFloatLiteral)1 AvroIntegerLiteral (com.linkedin.avroutil1.model.AvroIntegerLiteral)1 AvroLiteral (com.linkedin.avroutil1.model.AvroLiteral)1