Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 替换的freemarker模板字段中不需要的引号_Java_Json_Javabeans_Freemarker - Fatal编程技术网

Java 替换的freemarker模板字段中不需要的引号

Java 替换的freemarker模板字段中不需要的引号,java,json,javabeans,freemarker,Java,Json,Javabeans,Freemarker,我从Freemarker模板生成内容,但我在替换字段中得到引用值 对于JSON对象 { "name" : "Pepster" } 在模板中: Hi ${name}! 我明白了 当我想 Hi Pepster! 我为其提供的对象是一个JsonNode树,通过将我的对象映射到Jackson注释获得: class Name { @JsonProperty("name") public String mName; } 处理器: final ObjectMapper mapper

我从Freemarker模板生成内容,但我在替换字段中得到引用值

对于JSON对象

{
  "name" : "Pepster"
}
在模板中:

Hi ${name}!
我明白了

当我想

Hi Pepster!
我为其提供的对象是一个JsonNode树,通过将我的对象映射到Jackson注释获得:

class Name {
    @JsonProperty("name")
    public String mName;
}
处理器:

final ObjectMapper mapper = new ObjectMapper();
JsonNode jsonDocument = mapper.valueToTree(nameObject);
//...
template.process(jsonDocument, writer);

我觉得我缺少了某种配置?

FreeMarker没有添加引号,
JsonNode
toString()
方法肯定会添加引号。您需要使用一个定制的(已初始化的)
ObjectWrapper
,它知道应该调用
getTextValue()
(或类似的东西)来提取
字符串
值。JSON number也会有同样的问题,其中
ObjectWrapper
应该调用
getNumberValue()
。或者,如果您不想投资定制的
ObjectWrapper
${name.textValue}
当然可以工作,但是如果您有很多模板,这就有点尴尬了。

下面是一个定制ObjectWrapper的示例实现,它可以正确处理


解决方案缺少对Jackson NullNode的处理。NullNode应该通过返回一个总是生成null的模型工厂来处理。哦,谢谢@Nathan,我也遇到了这个问题,但是忘记更新答案了
final ObjectMapper mapper = new ObjectMapper();
JsonNode jsonDocument = mapper.valueToTree(nameObject);
//...
template.process(jsonDocument, writer);
package com.sample.templates;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.*;
import freemarker.core.CollectionAndSequence;
import freemarker.ext.beans.BeanModel;
import freemarker.ext.beans.BeansWrapper;
import freemarker.ext.beans.IteratorModel;
import freemarker.ext.util.ModelFactory;
import freemarker.template.*;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

class JsonAwareObjectWrapper extends DefaultObjectWrapper {
    public JsonAwareObjectWrapper(Version incompatibleImprovements) {
        super(incompatibleImprovements);
    }


    private static class JsonNullNodeModel {

        static final ModelFactory FACTORY = new ModelFactory() {

            public TemplateModel create(Object object, ObjectWrapper wrapper) {
                return null;
            }
        };

    }

    private static class JsonTextNodeModel extends BeanModel
            implements TemplateScalarModel {
        static final ModelFactory FACTORY =
                new ModelFactory() {
                    public TemplateModel create(Object object, ObjectWrapper wrapper) {
                        return new JsonTextNodeModel(object, (BeansWrapper) wrapper);
                    }
                };

        JsonTextNodeModel(Object object, BeansWrapper wrapper) {
            super(object, wrapper);
        }

        /**
         * Returns the result of calling {@link TextNode#asText()} on the wrapped
         * TextNode.
         */
        public String getAsString() {
            return ((TextNode) object).asText();
        }
    }

    private static class JsonNumberNodeModel extends
            BeanModel
            implements
            TemplateNumberModel {
        static final ModelFactory FACTORY =
                new ModelFactory() {
                    public TemplateModel create(Object object, ObjectWrapper wrapper) {
                        return new JsonNumberNodeModel(object, (BeansWrapper) wrapper);
                    }
                };

        JsonNumberNodeModel(Object object, BeansWrapper wrapper) {
            super(object, wrapper);
        }

        @Override
        public Number getAsNumber() throws TemplateModelException {
            return ((NumericNode) object).numberValue();
        }
    }

    private static class JsonBooleanNodeModel extends BeanModel implements TemplateBooleanModel {
        static final ModelFactory FACTORY =
                new ModelFactory() {
                    public TemplateModel create(Object object, ObjectWrapper wrapper) {
                        return new JsonBooleanNodeModel(object, (BeansWrapper) wrapper);
                    }
                };


        JsonBooleanNodeModel(Object object, BeansWrapper wrapper) {
            super(object, wrapper);
        }

        @Override
        public boolean getAsBoolean() throws TemplateModelException {
            return ((BooleanNode) object).asBoolean();
        }
    }

    private static class JsonPOJONodeModel extends BeanModel {
        static final ModelFactory FACTORY =
                new ModelFactory() {
                    public TemplateModel create(Object object, ObjectWrapper wrapper) {
                        return new JsonPOJONodeModel(((POJONode) object).getPojo(), (BeansWrapper) wrapper);
                    }
                };


        JsonPOJONodeModel(Object object, BeansWrapper wrapper) {
            super(object, wrapper);
        }
    }

    private static class JsonObjectNodeModel extends BeanModel {
        static final ModelFactory FACTORY =
                new ModelFactory() {
                    public TemplateModel create(Object object, ObjectWrapper wrapper) {
                        return new JsonObjectNodeModel(object, (BeansWrapper) wrapper);
                    }
                };
        JsonObjectNodeModel(Object object, BeansWrapper wrapper) {
            super(object, wrapper);
        }

        @Override
        public TemplateModel get(String key) throws TemplateModelException {
            ObjectNode objectNode = (ObjectNode) object;
            final JsonNode jsonNode = objectNode.get(key);
            if (jsonNode != null)
                return wrap(jsonNode);
            else
                return null;
        }

        @Override
        public boolean isEmpty() {
            ObjectNode objectNode = (ObjectNode) object;
            return objectNode.size() == 0;
        }

        @Override
        public int size() {
            ObjectNode objectNode = (ObjectNode) object;
            return objectNode.size();
        }

        @Override
        public TemplateCollectionModel keys() {
            ObjectNode objectNode = (ObjectNode) object;
            return new IteratorModel(objectNode.fieldNames(), wrapper);
        }

        @Override
        public TemplateCollectionModel values() throws TemplateModelException {
            ObjectNode objectNode = (ObjectNode) object;

            List<JsonNode> values = new ArrayList<>(size());
            final Iterator<Map.Entry<String, JsonNode>> it = objectNode.fields();
            while (it.hasNext()) {
                JsonNode value = it.next().getValue();
                values.add(value);
            }
            return new CollectionAndSequence(new SimpleSequence(values, wrapper));
        }
    }

    private static class JsonArrayNodeModel extends BeanModel
            implements
            TemplateCollectionModel,
            TemplateSequenceModel {
        static final ModelFactory FACTORY =
                new ModelFactory() {
                    public TemplateModel create(Object object, ObjectWrapper wrapper) {
                        return new JsonArrayNodeModel(object, (BeansWrapper) wrapper);
                    }
                };


        private class Iterator
                implements
                TemplateSequenceModel,
                TemplateModelIterator {
            private int position = 0;

            public boolean hasNext() {
                return position < length;
            }

            public TemplateModel get(int index)
                    throws
                    TemplateModelException {
                return JsonArrayNodeModel.this.get(index);
            }

            public TemplateModel next()
                    throws
                    TemplateModelException {
                return position < length ? get(position++) : null;
            }

            public int size() {
                return JsonArrayNodeModel.this.size();
            }
        }

        private final int length;

        JsonArrayNodeModel(Object array, BeansWrapper wrapper) {
            super(array, wrapper);
            ArrayNode arrayNode = (ArrayNode) array;

            length = arrayNode.size();
        }

        @Override
        public TemplateModelIterator iterator() {
            return new Iterator();
        }

        @Override
        public TemplateModel get(int index) throws TemplateModelException {
            try {
                return wrap(((ArrayNode) object).get(index));
            } catch (IndexOutOfBoundsException e) {
                return null;
            }
        }

        @Override
        public int size() {
            return length;
        }

        @Override
        public boolean isEmpty() {
            return length == 0;
        }
    }

    @Override
    protected ModelFactory getModelFactory(Class clazz) {
        if (TextNode.class.isAssignableFrom(clazz)) {
            return JsonTextNodeModel.FACTORY;
        } else if (NumericNode.class.isAssignableFrom(clazz)) {
            return JsonNumberNodeModel.FACTORY;
        } else if (BooleanNode.class.isAssignableFrom(clazz)) {
            return JsonBooleanNodeModel.FACTORY;
        } else if (POJONode.class.isAssignableFrom(clazz)) {
            return JsonPOJONodeModel.FACTORY;
        } else if (ArrayNode.class.isAssignableFrom(clazz)) {
            return JsonArrayNodeModel.FACTORY;
        } else if (ObjectNode.class.isAssignableFrom(clazz)) {
            return JsonObjectNodeModel.FACTORY;
        } else if (NullNode.class.isAssignableFrom(clazz)) {
            return JsonNullNodeModel.FACTORY;
        } else {
            return super.getModelFactory(clazz);
        }
    }
}
final ObjectNode objectNode = objectMapper.createObjectNode();
objectNode.put("string", "jsonValue");
objectNode.put("int", 10);
objectNode.put("float", 3.14f);
objectNode.put("bool", true);

final ArrayNode arrayNode = objectMapper.createArrayNode();
arrayNode.add("arrayValue0");
arrayNode.add("arrayValue1");
objectNode.set("array", arrayNode);

final ObjectNode subObject = objectMapper.createObjectNode();
subObject.put("bool", false);
objectNode.set("subobject", subObject);

PojoSample pojoSample = new PojoSample();
pojoSample.setName("pojo");
pojoSample.setValue(100);
objectNode.set("pojo", new POJONode(pojoSample));

SimpleHash model = new SimpleHash(objectWrapper);
model.put("form", request.getForm());
model.put("env", request.getEnvironment());
model.put("json", objectNode);


stringLoader.putTemplate("simple",
            "Json test: \n" +
            "String ${json.string}\n" +
            "Integer ${json.int}\n" +
            "Float ${json.float}\n" +
            "Boolean ${json.bool?c}\n" +
            "Sub Object ${json.subobject.bool?c}\n" +
            "Sub Array ${json.array[1]}\n" +
            "Pojo: name = ${json.pojo.name}, value = ${json.pojo.value}");
Template temp = cfg.getTemplate("simple");
StringWriter out = new StringWriter();
temp.process(model, out);