我有一个JSON字符串,我想在使用Jackson库构造JsonNode时更改该值。例如:-
input: {"name":"xyz","price":"90.00"}
output:{"name":"xyz-3","price":90.90}
我创建了自己的JsonFactory,并通过了自己的解析器。但我只能更改键,不能更改与键相关的值。
代码:
private static ObjectMapper create() {
ObjectMapper objectMapper = new ObjectMapper(new JsonFactory() {
@Override
protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException {
return new MyParser(super._createParser(data, offset, len, ctxt));
}
@Override
protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOException {
return new MyParser(super._createParser(in, ctxt));
}
@Override
protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException {
return new MyParser(super._createParser(r, ctxt));
}
@Override
protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt, boolean recyclable)
throws IOException {
return new MyParser(super._createParser(data, offset, len, ctxt, recyclable));
}
});
private static final class MyParser extends JsonParserDelegate {
private MyParser(JsonParser d) {
super(d);
}
@Override
public String getCurrentName() throws IOException, JsonParseException {
....
}
@Override
public String getText() throws IOException, JsonParseException {
...
}
@Override
public Object getCurrentValue() {
...
}
@Override
public String getValueAsString() throws IOException {
...
}
@Override
public String getValueAsString(String defaultValue) throws IOException {
...
}
}
下面是根据字符串构造JsonNode的代码。
mapper.readTree(jsonStr);
在这种情况下,当readTree方法被称为getMONtValue
或getValueAsString
方法不被调用时,所以我不能在创建JsonNode本身时更改值。json字符串也可以不同。基本上,我想从字符串构造一个JsonNode。所以绑定到特定的模式/bean不是一个好的选择。如何解决这个问题?TIA
添加版本2.7.4的更新代码:-
static class MyParser extends JsonParserDelegate {
MyParser(final JsonParser delegate) {
super(delegate);
}
@Override
public String getText() throws IOException {
final String text = super.getText();
if ("name".equals(getCurrentName())) {
return text + "-3";
}
return text;
}
@Override
public JsonToken nextToken() throws IOException {
if ("price".equals(getCurrentName())) {
// Advance token anyway
super.nextToken();
return JsonToken.VALUE_NUMBER_FLOAT;
}
return super.nextToken();
}
@Override
public int getCurrentTokenId() {
try {
if ("price".equals(getCurrentName())) {
return JsonTokenId.ID_NUMBER_FLOAT;
}
} catch (final IOException e) {
//
}
return super.getCurrentTokenId();
}
@Override
public NumberType getNumberType() throws IOException {
if ("price".equals(getCurrentName())) {
return NumberType.FLOAT;
}
return super.getNumberType();
}
@Override
public float getFloatValue() throws IOException {
return Float.parseFloat(getValueAsString("0")) + 0.09F;
}
@Override
public double getDoubleValue() throws IOException {
return Double.parseDouble(getValueAsString("0")) + 0.09D;
}
}
波姆。xml:-
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.8.7</version>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.8.7</version>
</dependency>
关于关注点的分离,您真的确定在解析的数据中混合解析和更改是一个好主意吗?
如果您仍然想这样做,您可以使用自定义解序列化器,并按照您想要的方式处理您想要的字段名和类型,例如:
class CustomDeserializer extends StdDeserializer<Entity> {
public CustomDeserializer(Class<Entity> t) {
super(t);
}
@Override
public Entity deserialize(JsonParser jp, DeserializationContext dc) throws IOException {
String name = null;
float price = 0;
JsonToken currentToken = null;
while ((currentToken = jp.nextValue()) != null) {
switch (currentToken) {
case VALUE_STRING:
switch (jp.getCurrentName()) {
case "name":
name = jp.getText() + "-3"; // change this text to whatever you want;
break;
case "price":
price = Float.parseFloat(jp.getText()); // parse
break;
default:
break;
}
break;
default:
break;
}
}
return new Entity(name, price);
}
}
注册自定义反序列化程序后,它可以在任何需要的对象映射器上工作:
@Test
public void customDeserialization() throws IOException {
// given
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Entity.class, new CustomDeserializer(Entity.class));
mapper.registerModule(module);
// when
Entity entity = mapper.readValue("{\"name\":\"xyz\",\"price\":\"90.00\"}", Entity.class);
// then
assertThat(entity.getName()).isEqualTo("xyz-3");
assertThat(entity.getPrice()).isEqualTo(90f);
}
编辑:2.7.*
和2.9.*
.
而2.9.*
能够区分双
和浮点
getDoubleValue()
getFloatValue()
而不是2.7.*
只使用
getDoubleValue()
即使是ID\u NUMBER\u FLOAT
代币
因此,您需要决定是否要保持复古兼容性。
您也可以覆盖两者,就像我在这里做的那样。
这就是定制MyParser
static class MyParser extends JsonParserDelegate {
MyParser(final JsonParser delegate) {
super(delegate);
}
@Override
public String getText() throws IOException {
final String text = super.getText();
if ("name".equals(getCurrentName())) {
return text + "-3";
}
return text;
}
@Override
public JsonToken nextToken() throws IOException {
if ("price".equals(getCurrentName())) {
// Advance token anyway
super.nextToken();
return JsonToken.VALUE_NUMBER_FLOAT;
}
return super.nextToken();
}
@Override
public int getCurrentTokenId() {
try {
if ("price".equals(getCurrentName())) {
return JsonTokenId.ID_NUMBER_FLOAT;
}
} catch (final IOException e) {
//
}
return super.getCurrentTokenId();
}
@Override
public NumberType getNumberType() throws IOException {
if ("price".equals(getCurrentName())) {
return NumberType.FLOAT;
}
return super.getNumberType();
}
@Override
public float getFloatValue() throws IOException {
return Float.parseFloat(getValueAsString("0")) + 0.09F;
}
@Override
public double getDoubleValue() throws IOException {
return Double.parseDouble(getValueAsString("0")) + 0.09D;
}
}
输出:{"name":"xyz-3","price": 90.09}
您的代码看起来很好,并且经过测试并正常工作;)
我有下面的班级结构。 问题1:方法将对象作为参数并返回字符串,它只是返回一个空字符串对象,而不是设置字符串的属性并返回它。为什么?如何返回对象的属性? 问题2:当map方法的参数名为时,它使用类中的属性生成实现,否则只生成空的对象。我很惊讶地发现mapstruct生成的不同实现也取决于参数名。有什么解释吗? 注意:对象在另一个对象中用作属性。在那里我需要上面提到的行为。现在我是这样管理的。@map
问题内容: 它应该是如此简单,但是在尝试一个小时的尴尬之后,我只是找不到它。 我需要获取一个JSON字符串,例如,解析为。 给 问题答案: 理查兹的答案略有不同,但可以使用字符串,因此可以将其简化为:
关于这里的问题 我们有两个字符串A和B,它们具有相同的超级字符集。我们需要更改这些字符串以获得两个相等的字符串。在每次移动中,我们可以执行以下操作之一: 1-交换字符串的两个连续字符 2-交换字符串的第一个字符和最后一个字符 可以在任一字符串上执行移动。为了获得两个相等的字符串,我们需要的最小移动次数是多少?输入格式和约束:输入的第一行和第二行包含两个字符串A和B。保证它们的字符超集相等。1个 看
问题内容: 我有一个bse64encoded字符串,来自外部源(Android商店)的公钥,我需要使用它来验证签名内容。如何将字符串转换为java.security.PublicKey接口的实例。如果这有所作为,我使用Java 6。 密钥是(可能)使用标准的Java库而不是有弹性的城堡生成的(它来自远程团队,所以我不确定)。他们的示例代码说使用Security.generatePublicKey(
下面是一个名为“containers”的表的片段。 如何将“产品”列更改为“字符变化[]”,并将相应的修饰符更改为默认值“{}”::字符变化[]?本质上,我想将字符串转换为字符串数组。注意,“产品”列对字符数没有限制。 抛出以下错误 错误:“products”列不能转换为不同类型的字符[]
我有一个.odt wordprocessing文件,要用libre office或Word处理,我需要用其他文本替换文本中的一串(20+)字符串。我知道.odt文件实际上是一个.zip文件,包含.xml文件,并且我需要访问content.xml。我是否将content.xml解压缩到一个流中,反序列化该流并使用LINQ或其他东西?或者有没有更简单的方法,使用一些现成的库?