1

我使用 Jackson 库生成这样的 json 字符串:

ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(model);

例如,这个剪断的代码会生成这样的东西:

{"x" : "This is x", "y" : "This is y"}

但我想生成这样的东西:

{'x' : 'This is x', 'y' : 'This is y'}

我的意思是如何用单引号字符串更改双引号字符串。我尝试像这样更改代码:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
String str = objectMapper.writeValueAsString(model);

但是这个剪断的代码会生成第一个。当然我可以用替换方法来处理这个问题,但我希望杰克逊图书馆为我做这件事。我该如何处理这个问题?

4

4 回答 4

2

objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);是关于在反序列化(JSON 到对象)中允许单引号,而不是根据需要序列化(对象到 JSON)。

在序列化中,问题似乎与 Jackson 1.X 的默认序列化程序有关。下面是杰克逊用来编写String值的代码。如您所见,双引号是硬编码的,因此无法通过配置更改:

@Override
public void writeString(String text)
    throws IOException, JsonGenerationException
{
    _verifyValueWrite("write text value");
    if (text == null) {
        _writeNull();
        return;
    }
    if (_outputTail >= _outputEnd) {
        _flushBuffer();
    }
    _outputBuffer[_outputTail++] = '"'; // <----------------- opening quote
    _writeString(text);                 // <----------------- string actual value
    // And finally, closing quotes
    if (_outputTail >= _outputEnd) {
        _flushBuffer();
    }
    _outputBuffer[_outputTail++] = '"'; // <----------------- closing quote
}

要实现您想要的,至少有两种选择:


1:使用正则表达式替换引号:

这是一种安全的方法,因为 Jackson 给出了"已经转义的双引号 ( ) ( \")。您所要做的就是转义单引号并切换"属性名称和值:

ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(model);
System.out.println("Received.: "+str);
str = str.replaceAll("'", "\\\\'"); // escapes all ' (turns all ' into \')
str = str.replaceAll("(?<!\\\\)\"", "'"); // turns all "bla" into 'bla'
System.out.println("Converted: "+str);

输出:

Received.: {"x":"ab\"c","y":"x\"y'z","z":15,"b":true}
Converted: {'x':'ab\"c','y':'x\"y\'z','z':15,'b':true}

或 2:JsonSerializer在每个String字段上使用自定义

声明自定义序列化器:

public class SingleQuoteStringSerializer extends JsonSerializer<String> {
    @Override
    public void serialize(String str, JsonGenerator jGen, SerializerProvider sP)
            throws IOException, JsonProcessingException {
        str = str.replace("'", "\\'"); // turns all ' into \'
        jGen.writeRawValue("'" + str + "'"); // write surrounded by single quote
    }
}

在要单引号的字段中使用它:

public class MyModel {
    @JsonSerialize(using = SingleQuoteStringSerializer.class)   
    private String x;
    ...

并照常进行(QUOTE_FIELD_NAMES == false用于取消引用字段名称):

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
String str = objectMapper.writeValueAsString(model);
System.out.println("Received.: "+str);

输出:

Received.: {x:'ab"c',y:'x"y\'z',z:15,b:true}

注意:由于您似乎想要将 JSON 嵌入到另一个中,因此最后一种方法可能还需要转义"s(请参阅参考资料x:'ab"c')。

于 2013-06-10T02:27:57.820 回答
1

正如我在评论中所说,这不是有效的 JSON,逃避它没有任何意义。您应该以不同的方式处理它。

您应该将该对象放在属性中。

我想你想要类似的东西

{"myString":"{\"fake json\":\"foo\"}"}

相反,您应该拥有:

{"myString":{"fake json":"foo"}}

这应该是处理这个问题的正确方法。

于 2013-06-09T21:06:42.440 回答
1

通过以下方式配置 ObjectMapper:

final ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

//this may be what you need
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
于 2013-06-09T11:03:19.647 回答
1

尝试调查 gson。在 gson 中看起来像这样。房子我的房子=新房子();Gson gson = 新 Gson(); 字符串 json = gson.toJson(myHouse); 完毕...

http://code.google.com/p/google-gson/

于 2013-06-09T11:12:06.033 回答