All Downloads are FREE. Search and download functionalities are using the official Maven repository.

shade.com.alibaba.fastjson2.JSONPathMulti Maven / Gradle / Ivy

There is a newer version: 1.3.7
Show newest version
package com.alibaba.fastjson2;

import com.alibaba.fastjson2.reader.FieldReader;
import com.alibaba.fastjson2.reader.ObjectReader;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

final class JSONPathMulti
        extends JSONPath {
    final List segments;
    final boolean ref;
    final boolean extractSupport;

    JSONPathMulti(String path, List segments, Feature... features) {
        super(path, features);
        this.segments = segments;

        boolean extractSupport = true;
        boolean ref = true;
        int size = segments.size();
        for (int i = 0; i < size - 1; i++) {
            JSONPathSegment segment = segments.get(i);
            if (segment instanceof JSONPathSegmentIndex) {
                if (((JSONPathSegmentIndex) segment).index < 0) {
                    extractSupport = false;
                }
                continue;
            }
            if (segment instanceof JSONPathSegmentName) {
                continue;
            }
            ref = false;
            if (i > 0) {
                JSONPathSegment prev = segments.get(i - 1);
                if (prev instanceof JSONPathSegment.CycleNameSegment && ((JSONPathSegment.CycleNameSegment) prev).shouldRecursive()
                        && segment instanceof JSONPathFilter.NameFilter) {
                    ((JSONPathFilter.NameFilter) segment).excludeArray();
                }
            }
            break;
        }
        this.extractSupport = extractSupport;
        this.ref = ref;
    }

    @Override
    public boolean remove(Object root) {
        Context context = null;

        int size = segments.size();
        if (size == 0) {
            return false;
        }

        for (int i = 0; i < size; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;
            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }
            context = new Context(this, context, segment, nextSegment, 0);
            if (i == 0) {
                context.root = root;
            }

            if (i == size - 1) {
                return segment.remove(context);
            }
            segment.eval(context);

            if (context.value == null) {
                return false;
            }
        }

        return false;
    }

    @Override
    public boolean contains(Object root) {
        Context context = null;

        int size = segments.size();
        if (size == 0) {
            return root != null;
        }

        for (int i = 0; i < size; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;
            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }
            context = new Context(this, context, segment, nextSegment, 0);
            if (i == 0) {
                context.root = root;
            }

            if (i == size - 1) {
                return segment.contains(context);
            }
            segment.eval(context);
        }

        return false;
    }

    @Override
    public boolean endsWithFilter() {
        int size = segments.size();
        JSONPathSegment last = segments.get(size - 1);
        return last instanceof JSONPathFilter;
    }

    @Override
    public JSONPath getParent() {
        int size = segments.size();
        if (size == 0) {
            return null;
        }

        if (size == 1) {
            return RootPath.INSTANCE;
        }

        if (size == 2) {
            return JSONPathSingle.of(segments.get(0));
        }

        StringBuilder buf = new StringBuilder();
        buf.append('$');
        List parentSegments = new ArrayList<>(size - 1);
        for (int i = 0, end = size - 1; i < end; i++) {
            JSONPathSegment segment = segments.get(i);
            parentSegments.add(segment);
            boolean array = segment instanceof JSONPathSegmentIndex
                    || segment instanceof JSONPathSegment.MultiIndexSegment
                    || segment instanceof JSONPathFilter;
            if (!array) {
                buf.append('.');
            }
            buf.append(segment);
        }

        String parentPath = buf.toString();
        if (size == 3) {
            new JSONPathTwoSegment(parentPath, segments.get(0), segments.get(1));
        }

        return new JSONPathMulti(parentPath, parentSegments);
    }

    @Override
    public boolean isRef() {
        return ref;
    }

    @Override
    public Object eval(Object root) {
        Context context = null;

        int size = segments.size();
        if (size == 0) {
            return root;
        }

        for (int i = 0; i < size; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;
            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }
            context = new Context(this, context, segment, nextSegment, 0);
            if (i == 0) {
                context.root = root;
            }

            if (i > 0) {
                JSONPathSegment prev = segments.get(i - 1);
                if (prev instanceof JSONPathSegment.CycleNameSegment && ((JSONPathSegment.CycleNameSegment) prev).shouldRecursive()
                        && segment instanceof JSONPathFilter.NameFilter) {
                    ((JSONPathFilter.NameFilter) segment).excludeArray();
                }
            }
            segment.eval(context);
        }

        Object contextValue = context.value;
        if ((context.path.features & Feature.AlwaysReturnList.mask) != 0) {
            if (contextValue == null) {
                contextValue = new JSONArray();
            } else if (!(contextValue instanceof List)) {
                contextValue = JSONArray.of(contextValue);
            }
        }
        return contextValue;
    }

    @Override
    public void set(Object root, Object value) {
        Context context = null;
        int size = segments.size();
        for (int i = 0; i < size - 1; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;
            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }
            context = new Context(this, context, segment, nextSegment, 0L);
            if (i == 0) {
                context.root = root;
            }

            segment.eval(context);
            if (context.value == null && nextSegment != null) {
                if (value == null) {
                    return;
                }

                Object parentObject;
                if (i == 0) {
                    parentObject = root;
                } else {
                    parentObject = context.parent.value;
                }

                Object emptyValue;
                if (nextSegment instanceof JSONPathSegmentIndex) {
                    emptyValue = new JSONArray();
                } else if (nextSegment instanceof JSONPathSegmentName) {
                    emptyValue = new JSONObject();
                } else {
                    return;
                }
                context.value = emptyValue;

                if (parentObject instanceof Map && segment instanceof JSONPathSegmentName) {
                    ((Map) parentObject).put(((JSONPathSegmentName) segment).name, emptyValue);
                } else if (parentObject instanceof List && segment instanceof JSONPathSegmentIndex) {
                    List list = (List) parentObject;
                    int index = ((JSONPathSegmentIndex) segment).index;
                    if (index == list.size()) {
                        list.add(emptyValue);
                    } else {
                        list.set(index, emptyValue);
                    }
                } else if (parentObject != null) {
                    Class parentObjectClass = parentObject.getClass();
                    JSONReader.Context readerContext = getReaderContext();
                    ObjectReader objectReader = readerContext.getObjectReader(parentObjectClass);
                    if (segment instanceof JSONPathSegmentName) {
                        FieldReader fieldReader = objectReader.getFieldReader(((JSONPathSegmentName) segment).nameHashCode);
                        if (fieldReader != null) {
                            ObjectReader fieldObjectReader = fieldReader.getObjectReader(readerContext);
                            Object fieldValue = fieldObjectReader.createInstance();
                            fieldReader.accept(parentObject, fieldValue);
                            context.value = fieldValue;
                        }
                    }
                }
            }
        }
        context = new Context(this, context, segments.get(0), null, 0L);
        context.root = root;

        JSONPathSegment segment = segments.get(size - 1);
        segment.set(context, value);
    }

    @Override
    public void set(Object root, Object value, JSONReader.Feature... readerFeatures) {
        long features = 0;
        for (JSONReader.Feature feature : readerFeatures) {
            features |= feature.mask;
        }

        Context context = null;
        int size = segments.size();
        for (int i = 0; i < size - 1; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;
            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }
            context = new Context(this, context, segment, nextSegment, features);
            if (i == 0) {
                context.root = root;
            }

            segment.eval(context);
        }
        context = new Context(this, context, segments.get(0), null, features);
        context.root = root;

        JSONPathSegment segment = segments.get(size - 1);
        segment.set(context, value);
    }

    @Override
    public void setCallback(Object root, BiFunction callback) {
        Context context = null;
        int size = segments.size();
        for (int i = 0; i < size - 1; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;
            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }
            context = new Context(this, context, segment, nextSegment, 0);
            if (i == 0) {
                context.root = root;
            }

            segment.eval(context);
        }
        context = new Context(this, context, segments.get(0), null, 0);
        context.root = root;

        JSONPathSegment segment = segments.get(size - 1);
        segment.setCallback(context, callback);
    }

    @Override
    public void setInt(Object rootObject, int value) {
        set(rootObject, value);
    }

    @Override
    public void setLong(Object rootObject, long value) {
        set(rootObject, value);
    }

    @Override
    public Object extract(JSONReader jsonReader) {
        if (jsonReader == null) {
            return null;
        }

        int size = segments.size();
        if (size == 0) {
            return null;
        }

        if (!extractSupport) {
            Object root = jsonReader.readAny();
            return eval(root);
        }

        boolean eval = false;
        Context context = null;
        for (int i = 0; i < size; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;

            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }

            context = new Context(this, context, segment, nextSegment, 0);
            if (eval) {
                segment.eval(context);
            } else {
                segment.accept(jsonReader, context);
            }

            if (context.eval) {
                eval = true;
                if (context.value == null) {
                    break;
                }
            }
        }

        Object value = context.value;
        if (value instanceof Sequence) {
            value = ((Sequence) value).values;
        }

        if ((features & Feature.AlwaysReturnList.mask) != 0) {
            if (value == null) {
                value = new JSONArray();
            } else if (!(value instanceof List)) {
                value = JSONArray.of(value);
            }
        }
        return value;
    }

    @Override
    public String extractScalar(JSONReader jsonReader) {
        int size = segments.size();
        if (size == 0) {
            return null;
        }

        boolean eval = false;
        Context context = null;
        for (int i = 0; i < size; i++) {
            JSONPathSegment segment = segments.get(i);
            JSONPathSegment nextSegment = null;

            int nextIndex = i + 1;
            if (nextIndex < size) {
                nextSegment = segments.get(nextIndex);
            }

            context = new Context(this, context, segment, nextSegment, 0);
            if (eval) {
                segment.eval(context);
            } else {
                segment.accept(jsonReader, context);
            }

            if (context.eval) {
                eval = true;
                if (context.value == null) {
                    break;
                }
            }
        }

        return JSON.toJSONString(context.value);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy