Package com.eviware.soapui.support

Source Code of com.eviware.soapui.support.JsonPathFacade$JsonWriteDecorator

/*
*  SoapUI, copyright (C) 2004-2014 smartbear.com
*
*  SoapUI is free software; you can redistribute it and/or modify it under the
*  terms of version 2.1 of the GNU Lesser General Public License as published by
*  the Free Software Foundation.
*
*  SoapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
*  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*  See the GNU Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.support;

import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.internal.PathToken;
import com.jayway.jsonpath.internal.PathTokenizer;
import com.jayway.jsonpath.internal.filter.PathTokenFilter;
import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.groovy.JsonSlurper;

import java.lang.reflect.Field;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import static com.eviware.soapui.support.JsonUtil.isValidJson;

public class JsonPathFacade {

    private String currentJson;
    private Object jsonObject;

    public JsonPathFacade(String targetJson) {
        if (!isValidJson(targetJson)) {
            throw new IllegalArgumentException("Invalid JSON: " + targetJson);
        }
        this.currentJson = targetJson;
        jsonObject = new JsonSlurper().parseText(targetJson);
    }

    public String readStringValue(String jsonPathExpression) {
        return String.valueOf(readObjectValue(jsonPathExpression));
    }

    public void writeValue(String jsonPathExpression, Object value) {
        PlainJavaJsonProvider provider = new PlainJavaJsonProvider();
        Configuration configuration = Configuration.builder().jsonProvider(provider).build();
        jsonObject = provider.parse(currentJson);
        JsonPath path = JsonPath.compile(jsonPathExpression);
        LinkedList<PathToken> pathTokens = getPathTokensFrom(path);
        PathToken endToken = pathTokens.removeLast();
        int index = pathTokens.size();
        JsonWriteDecorator writeDecorator = new JsonWriteDecorator(provider, index, endToken, value);
        pathTokens.addLast(writeDecorator);
        path.read(jsonObject, configuration);
        jsonObject = MutableValue.FROM_MUTABLE_VALUE.apply(jsonObject);
        currentJson = buildJsonStringFrom(jsonObject);
    }

    private String buildJsonStringFrom(Object sourceObject) {
        Object json = makeJSONObject(sourceObject);
        return json instanceof JSON ? ((JSON) json).toString(3) : json.toString();
    }

    private Object makeJSONObject(Object sourceObject) {
        if (sourceObject instanceof Map) {
            JSONObject jsonObject = new JSONObject();
            Map sourceMap = (Map) sourceObject;
            for (Object key : sourceMap.keySet()) {
                jsonObject.put(key, makeJSONObject(sourceMap.get(key)));
            }
            return jsonObject;
        } else if (sourceObject instanceof List) {
            List sourceList = (List) sourceObject;
            JSONArray array = new JSONArray();
            for (Object element : sourceList) {
                array.add(makeJSONObject(element));
            }
            return array;
        } else {
            return sourceObject;
        }
    }

    private void removeMutableWrappersFrom(JSON jsonObject) {
        if (jsonObject.isArray()) {
            JSONArray array = (JSONArray) jsonObject;
            for (int i = 0; i < array.size(); i++) {
                array.set(i, removeMutableWrapperFrom(array.get(i)));
            }
        } else if (jsonObject instanceof JSONObject) {
            JSONObject object = (JSONObject) jsonObject;
            for (Object key : object.keySet()) {
                object.put(key, removeMutableWrapperFrom(object.get(key)));
            }
        }
    }

    private Object removeMutableWrapperFrom(Object o) {
        Object value = MutableValue.extractValueFromMutable(o);
        if (value instanceof JSON) {
            removeMutableWrappersFrom((JSON) value);
        }
        return value;
    }

    private LinkedList<PathToken> getPathTokensFrom(JsonPath jsonPathObject) {
        try {
            Field tokenizerField = JsonPath.class.getDeclaredField("tokenizer");
            tokenizerField.setAccessible(true);
            PathTokenizer tokenizer = (PathTokenizer) tokenizerField.get(jsonPathObject);
            Field pathTokensField = PathTokenizer.class.getDeclaredField("pathTokens");
            pathTokensField.setAccessible(true);
            return (LinkedList<PathToken>) pathTokensField.get(tokenizer);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }


    public Object getJSON() {
        return jsonObject;
    }

    public String getCurrentJson() {
        return currentJson;
    }

    public <T> T readObjectValue(String jsonPathExpression) {
        PlainJavaJsonProvider provider = new PlainJavaJsonProvider();
        Configuration configuration = Configuration.builder().jsonProvider(provider).build();
        JsonPath jsonPath = JsonPath.compile(jsonPathExpression);
        return jsonPath.read(jsonObject, configuration);
    }

    private class JsonWriteDecorator extends PathToken {
        private final PlainJavaJsonProvider provider;
        private final Object value;

        public JsonWriteDecorator(PlainJavaJsonProvider provider, int index, PathToken endToken, Object value) {
            super(endToken.getFragment(), index, true);
            this.provider = provider;
            this.value = value;
        }

        @Override
        public PathTokenFilter getFilter() {
            // WORKAROUND: ideally we would use a decorator PathTokenFilter instead, but the PathTokenFilter constructor
            // is package protected. Unfortunately this entails that we can't reuse the provider after this step.
            provider.setValueToWrite(value);
            return super.getFilter();
        }

    }
}
TOP

Related Classes of com.eviware.soapui.support.JsonPathFacade$JsonWriteDecorator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.