Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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.facebook.presto.operator.scalar;
 
 
 
 import static com.facebook.presto.spi.StandardErrorCode.INVALID_FUNCTION_ARGUMENT;
 import static com.fasterxml.jackson.core.JsonFactory.Feature.CANONICALIZE_FIELD_NAMES;
 import static com.fasterxml.jackson.core.JsonToken.END_ARRAY;
 import static com.fasterxml.jackson.core.JsonToken.END_OBJECT;
 import static com.fasterxml.jackson.core.JsonToken.FIELD_NAME;
 import static com.fasterxml.jackson.core.JsonToken.START_ARRAY;
 import static com.fasterxml.jackson.core.JsonToken.START_OBJECT;
 import static com.fasterxml.jackson.core.JsonToken.VALUE_NULL;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.nio.charset.StandardCharsets.UTF_8;

Extracts values from JSON

Supports the following JSON path primitives:

    $ : Root object
    . or [] : Child operator
   [] : Subscript operator for array
 

Supported JSON Path Examples:

    { "store": {
        "book": [
          { "category": "reference",
            "author": "Nigel Rees",
            "title": "Sayings of the Century",
            "price": 8.95,
            "contributors": [["Adam", "Levine"], ["Bob", "Strong"]]
          },
          { "category": "fiction",
            "author": "Evelyn Waugh",
            "title": "Sword of Honour",
            "price": 12.99,
            "isbn": "0-553-21311-3",
            "last_owner": null
          }
        ],
        "bicycle": {
          "color": "red",
          "price": 19.95
        }
      }
    }
 

With only scalar values using dot-notation of path:

    $.store.book[0].author => Nigel Rees
    $.store.bicycle.price => 19.95
    $.store.book[0].isbn => NULL (Doesn't exist becomes java null)
    $.store.book[1].last_owner => NULL (json null becomes java null)
    $.store.book[0].contributors[0][1] => Levine
 

With json values using dot-notation of path:

    $.store.book[0].author => "Nigel Rees"
    $.store.bicycle.price => 19.95
    $.store.book[0].isbn => NULL (Doesn't exist becomes java null)
    $.store.book[1].last_owner => null (json null becomes the string "null")
    $.store.book[0].contributors[0] => ["Adam", "Levine"]
    $.store.bicycle => {"color": "red", "price": 19.95}
 
With only scalar values using bracket-notation of path:
    $["store"]["book"][0]["author"] => Nigel Rees
    $["store"]["bicycle"]["price"] => 19.95
    $["store"]["book"][0]["isbn"] => NULL (Doesn't exist becomes java null)
    $["store"]["book"][1]["last_owner"] => NULL (json null becomes java null)
    $["store"]["book"][0]["contributors"][0][1] => Levine
 

With json values using bracket-notation of path:

    $["store"]["book"][0]["author"] => "Nigel Rees"
    $["store"]["bicycle"]["price"] => 19.95
    $["store"]["book"][0]["isbn"] => NULL (Doesn't exist becomes java null)
    $["store"]["book"][1]["last_owner"] => null (json null becomes the string "null")
    $["store"]["book"][0]["contributors"][0] => ["Adam", "Levine"]
    $["store"]["bicycle"] => {"color": "red", "price": 19.95}
 
public final class JsonExtract
    private static final int ESTIMATED_JSON_OUTPUT_SIZE = 512;
    private static final JsonFactory JSON_FACTORY = new JsonFactory()
            .disable();
    private JsonExtract() {}
    public static <T> T extract(Slice jsonInputJsonExtractor<T> jsonExtractor)
    {
        checkNotNull(jsonInput"jsonInput is null");
        try {
            try (JsonParser jsonParser = .createJsonParser(jsonInput.getInput())) {
                // Initialize by advancing to first token and make sure it exists
                if (jsonParser.nextToken() == null) {
                    throw new JsonParseException("Missing starting token"jsonParser.getCurrentLocation());
                }
                return jsonExtractor.extract(jsonParser);
            }
        }
        catch (JsonParseException e) {
            // Return null if we failed to parse something
            return null;
        }
        catch (IOException e) {
            throw Throwables.propagate(e);
        }
    }
    public static <T> JsonExtractor<T> generateExtractor(String pathJsonExtractor<T> rootExtractor)
    {
        return generateExtractor(pathrootExtractorfalse);
    }
    public static <T> JsonExtractor<T> generateExtractor(String pathJsonExtractor<T> rootExtractorboolean exceptionOnOutOfBounds)
    {
        ImmutableList<Stringtokens = ImmutableList.copyOf(new JsonPathTokenizer(path));
        JsonExtractor<T> jsonExtractor = rootExtractor;
        for (String token : tokens.reverse()) {
            jsonExtractor = new ObjectFieldJsonExtractor<>(tokenjsonExtractorexceptionOnOutOfBounds);
        }
        return jsonExtractor;
    }
    public interface JsonExtractor<T>
    {
        
Executes the extraction on the existing content of the JsonParser and outputs the match.

Notes:

  • JsonParser must be on the FIRST token of the value to be processed when extract is called
  • INVARIANT: when extract() returns, the current token of the parser will be the LAST token of the value

Returns:
the value, or null if not applicable
        T extract(JsonParser jsonParser)
                throws IOException;
    }
    public static class ObjectFieldJsonExtractor<T>
            implements JsonExtractor<T>
    {
        private final SerializedString fieldName;
        private final JsonExtractor<? extends T> delegate;
        private final int index;
        private final boolean exceptionOnOutOfBounds;
        public ObjectFieldJsonExtractor(String fieldNameJsonExtractor<? extends T> delegate)
        {
            this(fieldNamedelegatefalse);
        }
        public ObjectFieldJsonExtractor(String fieldNameJsonExtractor<? extends T> delegateboolean exceptionOnOutOfBounds)
        {
            this. = new SerializedString(checkNotNull(fieldName"fieldName is null"));
            this. = checkNotNull(delegate"delegate is null");
            this. = exceptionOnOutOfBounds;
            this. = tryParseInt(fieldName, -1);
        }
        @Override
        public T extract(JsonParser jsonParser)
                throws IOException
        {
            if (jsonParser.getCurrentToken() == ) {
                return processJsonObject(jsonParser);
            }
            if (jsonParser.getCurrentToken() == ) {
                return processJsonArray(jsonParser);
            }
            throw new JsonParseException("Expected a JSON object or array"jsonParser.getCurrentLocation());
        }
        public T processJsonObject(JsonParser jsonParser)
                throws IOException
        {
            while (!jsonParser.nextFieldName()) {
                if (!jsonParser.hasCurrentToken()) {
                    throw new JsonParseException("Unexpected end of object"jsonParser.getCurrentLocation());
                }
                if (jsonParser.getCurrentToken() == ) {
                    // Unable to find matching field
                    return null;
                }
                jsonParser.skipChildren(); // Skip nested structure if currently at the start of one
            }
            jsonParser.nextToken(); // Shift to first token of the value
            return .extract(jsonParser);
        }
        public T processJsonArray(JsonParser jsonParser)
                throws IOException
        {
            int currentIndex = 0;
            while (true) {
                JsonToken token = jsonParser.nextToken();
                if (token == null) {
                    throw new JsonParseException("Unexpected end of array"jsonParser.getCurrentLocation());
                }
                if (token == ) {
                    // Index out of bounds
                    if () {
                        throw new PrestoException("Index out of bounds");
                    }
                    return null;
                }
                if (currentIndex == ) {
                    break;
                }
                currentIndex++;
                jsonParser.skipChildren(); // Skip nested structure if currently at the start of one
            }
            return .extract(jsonParser);
        }
    }
    public static class ScalarValueJsonExtractor
            implements JsonExtractor<Slice>
    {
        @Override
        public Slice extract(JsonParser jsonParser)
                throws IOException
        {
            JsonToken token = jsonParser.getCurrentToken();
            if (token == null) {
                throw new JsonParseException("Unexpected end of value"jsonParser.getCurrentLocation());
            }
            if (!token.isScalarValue() || token == ) {
                return null;
            }
            return Slices.wrappedBuffer(jsonParser.getText().getBytes());
        }
    }
    public static class JsonValueJsonExtractor
            implements JsonExtractor<Slice>
    {
        @Override
        public Slice extract(JsonParser jsonParser)
                throws IOException
        {
            if (!jsonParser.hasCurrentToken()) {
                throw new JsonParseException("Unexpected end of value"jsonParser.getCurrentLocation());
            }
            DynamicSliceOutput dynamicSliceOutput = new DynamicSliceOutput();
            try (JsonGenerator jsonGenerator = .createJsonGenerator(dynamicSliceOutput)) {
                jsonGenerator.copyCurrentStructure(jsonParser);
            }
            return dynamicSliceOutput.slice();
        }
    }
    public static class JsonSizeExtractor
            implements JsonExtractor<Long>
    {
        @Override
        public Long extract(JsonParser jsonParser)
                throws IOException
        {
            if (!jsonParser.hasCurrentToken()) {
                throw new JsonParseException("Unexpected end of value"jsonParser.getCurrentLocation());
            }
            if (jsonParser.getCurrentToken() == ) {
                long length = 0;
                while (true) {
                    JsonToken token = jsonParser.nextToken();
                    if (token == null) {
                        return null;
                    }
                    if (token == ) {
                        return length;
                    }
                    jsonParser.skipChildren();
                    length++;
                }
            }
            if (jsonParser.getCurrentToken() == ) {
                long length = 0;
                while (true) {
                    JsonToken token = jsonParser.nextToken();
                    if (token == null) {
                        return null;
                    }
                    if (token == ) {
                        return length;
                    }
                    if (token == ) {
                        length++;
                    }
                    else {
                        jsonParser.skipChildren();
                    }
                }
            }
            return 0L;
        }
    }
    private static int tryParseInt(String fieldNameint defaultValue)
    {
        int index = defaultValue;
        try {
            index = Integer.parseInt(fieldName);
        }
        catch (NumberFormatException ignored) {
        }
        return index;
    }
New to GrepCode? Check out our FAQ X