【问题标题】:Parsing JSON SCHEMA using GSON without predefined object in java使用 GSON 解析 JSON SCHEMA,而 Java 中没有预定义的对象
【发布时间】:2016-07-21 11:28:49
【问题描述】:

需要有关如何为复杂对象解析 JSON“SCHEMA”的指导,以便它仅使用 GSON 创建键值对。我的目标是获取所有父子列表

Gson gson=new GsonBuilder().setPrettyPrinting().create();
JsonReader reader = new JsonReader(
    new InputStreamReader(
        new FileInputStream("C:\\Users\\ravr\\Desktop\\inputJSONSChema.json"), 
        "UTF-8"
    )
);

JsonParser parser = new JsonParser();
JsonObject parentObject=parser.parse( reader ).getAsJsonObject();
//parseJsonObjectRecursive(parentObject);

Map<String, Object> map = gson.fromJson(
    parentObject, 
    new TypeToken<Map<String, Object>>(){}.getType()
);

System.out.println(map);
Iterator<Map.Entry<String, Object>> mapItr=map.entrySet().iterator();

while(mapItr.hasNext()) {
    Map.Entry<String, Object> obj=(Entry<String, Object>) mapItr.next();
    System.out.println("Key->" + obj.getKey());

    if("properties".equalsIgnoreCase(obj.getKey())) {

    } else if("items".equalsIgnoreCase(obj.getKey())) {

    }
}

【问题讨论】:

    标签: java json parsing jsonschema


    【解决方案1】:

    最后我找到了一种肮脏的方法。

    我创建了一个 JSONSchemaElement pojo,它是具有父子概念的通用 pojo,并将向其添加元素。

    public class JSONSchemaElement {
    
    private String elementName;
    private JsonSchemaTagEnum.ELEMENT_TYPE elementType;
    private String elementValue;
    private String minItems;
    private String maxItems;
    private boolean hasChildren;
    private List<JSONSchemaElement> children = new ArrayList<>();
    
    
    
    public void addChildElement(JSONSchemaElement childElement) {
        children.add( childElement );
    }
    
    /**
     * @return the elementName
     */
    public String getElementName() {
        return elementName;
    }
    
    /**
     * @param elementName
     *            the elementName to set
     */
    public void setElementName(String elementName) {
        this.elementName = elementName;
    }
    
    /**
     * @return the elementType
     */
    public JsonSchemaTagEnum.ELEMENT_TYPE getElementType() {
        return elementType;
    }
    
    /**
     * @param elementType
     *            the elementType to set
     */
    public void setElementType(JsonSchemaTagEnum.ELEMENT_TYPE elementType) {
        this.elementType = elementType;
    }
    
    /**
     * @return the elementValue
     */
    public String getElementValue() {
        return elementValue;
    }
    
    /**
     * @param elementValue
     *            the elementValue to set
     */
    public void setElementValue(String elementValue) {
        this.elementValue = elementValue;
    }
    
    /**
     * @return the minItems
     */
    public String getMinItems() {
        return minItems;
    }
    
    /**
     * @param minItems
     *            the minItems to set
     */
    public void setMinItems(String minItems) {
        this.minItems = minItems;
    }
    
    /**
     * @return the maxItems
     */
    public String getMaxItems() {
        return maxItems;
    }
    
    /**
     * @param maxItems
     *            the maxItems to set
     */
    public void setMaxItems(String maxItems) {
        this.maxItems = maxItems;
    }
    
    /**
     * @return the hasChildren
     */
    public boolean isHasChildren() {
        return hasChildren;
    }
    
    /**
     * @param hasChildren
     *            the hasChildren to set
     */
    public void setHasChildren(boolean hasChildren) {
        this.hasChildren = hasChildren;
    }
    
    /**
     * @return the children
     */
    public List<JSONSchemaElement> getChildren() {
        return children;
    }
    
    /**
     * @param children
     *            the children to set
     */
    public void setChildren(List<JSONSchemaElement> children) {
        this.children = children;
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ( ( children == null ) ? 0 : children.hashCode() );
        result = prime * result + ( ( elementName == null ) ? 0 : elementName.hashCode() );
        result = prime * result + ( ( elementType == null ) ? 0 : elementType.hashCode() );
        result = prime * result + ( ( elementValue == null ) ? 0 : elementValue.hashCode() );
        result = prime * result + ( hasChildren ? 1231 : 1237 );
        result = prime * result + ( ( maxItems == null ) ? 0 : maxItems.hashCode() );
        result = prime * result + ( ( minItems == null ) ? 0 : minItems.hashCode() );
        return result;
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals(Object obj) {
        if ( this == obj ) {
            return true;
        }
        if ( obj == null ) {
            return false;
        }
        if ( getClass() != obj.getClass() ) {
            return false;
        }
        JSONSchemaElement other = (JSONSchemaElement) obj;
        if ( children == null ) {
            if ( other.children != null ) {
                return false;
            }
        }
        else if ( !children.equals( other.children ) ) {
            return false;
        }
        if ( elementName == null ) {
            if ( other.elementName != null ) {
                return false;
            }
        }
        else if ( !elementName.equals( other.elementName ) ) {
            return false;
        }
        if ( elementType != other.elementType ) {
            return false;
        }
        if ( elementValue == null ) {
            if ( other.elementValue != null ) {
                return false;
            }
        }
        else if ( !elementValue.equals( other.elementValue ) ) {
            return false;
        }
        if ( hasChildren != other.hasChildren ) {
            return false;
        }
        if ( maxItems == null ) {
            if ( other.maxItems != null ) {
                return false;
            }
        }
        else if ( !maxItems.equals( other.maxItems ) ) {
            return false;
        }
        if ( minItems == null ) {
            if ( other.minItems != null ) {
                return false;
            }
        }
        else if ( !minItems.equals( other.minItems ) ) {
            return false;
        }
        return true;
    }
    
    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return "JSONSchemaElement [elementName=" + elementName + ", elementType=" + elementType + ", elementValue="
                + elementValue + ", minItems=" + minItems + ", maxItems=" + maxItems + ", hasChildren=" + hasChildren
                + ", children=" + children + "]";
    }
    

    }

    然后在下面的单例类的方法中调用 parseJsonSchema 方法,如下所示。这里我们构造了根节点,然后传入递归方法parseJsonSchema。

    JSONSchemaElement parentNode = null;
            try {
                JsonParser parser = new JsonParser();
                Preconditions.checkState( StringUtils.isNotEmpty( jsonSchema ), "JSON Schema Is NULL !!! " );
                JsonObject parentObject = parser.parse( jsonSchema ).getAsJsonObject();
    
                parentNode = new JSONSchemaElement();
                parentNode.setElementName( JsonSchemaTagEnum.ROOT_NODE.name() );
                parentNode.setHasChildren( true );
                parentNode.setElementType( JsonSchemaTagEnum.ELEMENT_TYPE.COMPLEX_TYPE );
                parseJSONSchema( parentObject, parentNode );
    
                if ( LOGGER.isDebugEnabled() ) {
                    LOGGER.debug( "After Parsing element->" + parentNode );
                }
            }
            catch ( Exception e ) {
                LOGGER.error( e.getMessage(), e );
            }
            if ( LOGGER.isDebugEnabled() ) {
                LOGGER.debug(
                        "-------------------- JSONSchemaUtility:fetchDecomposedJSONSchemaElementFromJsonSchema:: END ----------------------------------" );
            }
    
    
    
    /**
     * 
     * @param parentObject
     * @param parentlement
     */
    private void parseJSONSchema(JsonObject parentObject, JSONSchemaElement parentlement) {
    
        Set<Map.Entry<String, JsonElement>> entries = parentObject.entrySet();
        for ( Map.Entry<String, JsonElement> entry : entries ) {
            JSONSchemaElement element = new JSONSchemaElement();
            if ( LOGGER.isDebugEnabled() ) {
                LOGGER.debug( "Entry Key->" + entry.getKey() );
                LOGGER.debug( "Entry VALUE->" + entry.getValue() );
            }
            if ( entry.getValue().isJsonObject() ) {
                String key = entry.getKey();
                element.setElementName( key.toUpperCase() );
                element.setElementType( JsonSchemaTagEnum.ELEMENT_TYPE.COMPLEX_TYPE );
                element.setHasChildren( true );
                if ( !rejectKeyList.contains( entry.getKey().toUpperCase() ) ) {
                    setPrimitiveType( entry, element );
    
                }
                /**
                 * create child
                 */
                parseJSONSchema( entry.getValue().getAsJsonObject(), element );
                /**
                 * Pull Element from bottom to this key=> items->properties->actual element as ITEMS,PROPERTIES TAGS of
                 * JSON is not required
                 */
                element = pullChildFromBottomToTop( parentlement, element, key );
                if ( LOGGER.isDebugEnabled() ) {
                    LOGGER.debug( "************** Returning control back !!!!!!!!!!!" );
                }
    
            }
            else {
                if ( !JsonSchemaTagEnum.TYPE.name().equalsIgnoreCase( entry.getKey() ) ) {
    
                    if ( JsonSchemaTagEnum.MIN_ITEMS.name().equalsIgnoreCase( entry.getKey() ) ) {
                        if ( entry.getValue().isJsonPrimitive() ) {
                            parentlement.setMinItems( entry.getValue().getAsString() );
                        }
                        else if ( entry.getValue().isJsonNull() ) {
                            parentlement.setMinItems( entry.getValue().getAsJsonNull().toString() );
                        }
                    }
                    else if ( JsonSchemaTagEnum.MAX_ITEMS.name().equalsIgnoreCase( entry.getKey() ) ) {
                        if ( entry.getValue().isJsonPrimitive() ) {
                            parentlement.setMaxItems( entry.getValue().getAsString() );
                        }
                        else if ( entry.getValue().isJsonNull() ) {
                            parentlement.setMaxItems( entry.getValue().getAsJsonNull().toString() );
                        }
                    }
                    else {
                        element.setElementName( entry.getKey().toUpperCase() );
                        element.setElementType( JsonSchemaTagEnum.ELEMENT_TYPE.SIMPLE_TYPE );
                        if ( entry.getValue().isJsonArray() ) {
                            element.setElementValue( entry.getValue().getAsJsonArray().toString() );
                        }
                        else if ( entry.getValue().isJsonPrimitive() ) {
                            element.setElementValue( entry.getValue().getAsString() );
                        }
                        else if ( entry.getValue().isJsonNull() ) {
                            element.setElementValue( entry.getValue().getAsJsonNull().toString() );
                        }
                        element.setHasChildren( false );
                    }
    
                }
    
            }
            if ( null != element && null != element.getElementName() && element.getElementName().length() > 0 ) {
                parentlement.addChildElement( element );
            }
    
        }
    
    }
    
    /**
     * 
     * @param parentlement
     * @param element
     * @param key
     * @return
     */
    private JSONSchemaElement pullChildFromBottomToTop(JSONSchemaElement parentlement, JSONSchemaElement element,
            String key) {
        if ( JsonSchemaTagEnum.PROPERTIES.name().equalsIgnoreCase( key )
                || JsonSchemaTagEnum.ITEMS.name().equalsIgnoreCase( key ) ) {
            if ( LOGGER.isDebugEnabled() ) {
                LOGGER.debug( "For Properties Type key->" + element );
            }
            parentlement.setChildren( element.getChildren() );
            element.setChildren( null );
            if ( JsonSchemaTagEnum.ITEMS.name().equalsIgnoreCase( key ) ) {
                if ( null == parentlement.getMinItems() ) {
                    parentlement.setMinItems( element.getMinItems() );
                }
                if ( null == parentlement.getMaxItems() ) {
                    parentlement.setMaxItems( element.getMaxItems() );
                }
            }
            element = null;
    
        }
        return element;
    }
    
    /**
     * 
     * @param entry
     * @param element
     */
    private void setPrimitiveType(Map.Entry<String, JsonElement> entry, JSONSchemaElement element) {
        Gson gson = new Gson();
        String jsonTypeCasted = gson.toJson( entry.getValue() );
        String formattedJsonString = ( ( ( jsonTypeCasted.replaceAll( "\\{", "" ).trim() ).replaceAll( "\\}", "" )
                .trim() ).replaceAll( "\"", "" ) ).trim();
        String[] splitted = formattedJsonString.split( ":" );
        if ( splitted.length == 2 ) {
            String validPrimitiveType = isValidJsonPrimitiveDataType( splitted[1] );
            Preconditions.checkNotNull( validPrimitiveType,
                    "Data Type Mentioned In JSON Schema Is Not Supported By JSON: Valid Primitive Data Type Are NUMBER,STRING,BOOLEAN" );
            element.setElementValue( validPrimitiveType.toUpperCase() );
            element.setElementType( JsonSchemaTagEnum.ELEMENT_TYPE.SIMPLE_TYPE );
            element.setHasChildren( false );
        }
        gson = null;
    }
    
    private String isValidJsonPrimitiveDataType(String inputPrimitiveType) {
        String jsonPrimitiveDataType = null;
        if ( JSON_DATA_TYPE.STRING.toString().equalsIgnoreCase( inputPrimitiveType ) ) {
            jsonPrimitiveDataType = JSON_DATA_TYPE.STRING.toString();
        }
        else if ( JSON_DATA_TYPE.NUMBER.toString().equalsIgnoreCase( inputPrimitiveType ) ) {
            jsonPrimitiveDataType = JSON_DATA_TYPE.NUMBER.toString();
        }
        else if ( JSON_DATA_TYPE.BOOLEAN.toString().equalsIgnoreCase( inputPrimitiveType ) ) {
            jsonPrimitiveDataType = JSON_DATA_TYPE.BOOLEAN.toString();
        }
        else {
            if ( LOGGER.isDebugEnabled() ) {
                LOGGER.debug( "This Data Type Is Not Supproted in JSON->" + inputPrimitiveType );
            }
            jsonPrimitiveDataType = null;
        }
    
        return jsonPrimitiveDataType;
    }
    

    }

    【讨论】:

    • 也许使用 JayWay JsonPaths 是一种更好的方法......使用 Json 等效的 XPath 来过滤您想要的节点。我过去曾使用过它,并且正在考虑将来为我正在从事的项目使用类似的东西:) github.com/json-path/JsonPath
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多