Разбор данных JSON с данными JSON в одном поле [дубликат]

Чтобы использовать методы и член объекта, вам сначала нужно создать этот объект. Если вы его не создали (переменная, которая должна содержать объект, не инициализируется), но вы пытаетесь использовать его методы или переменные, вы получите эту ошибку.

Иногда вы можете просто забыть инициализировать .

Отредактировано: new не может вернуть значение null, но исключение огня при ошибке. Давно это было на некоторых языках, но не больше. Спасибо @John Saunders за указание на это.

80
задан skaffman 24 January 2011 в 17:11
поделиться

9 ответов

@JsonRawValue предназначен только для сериализации, так как обратное направление немного сложнее для обработки. Фактически он был добавлен, чтобы разрешить впрыскивание предварительно закодированного контента.

Я предполагаю, что можно было бы добавить поддержку для обратного, хотя это было бы довольно неудобно: контент должен быть проанализирован, записанный обратно в «сырую» форму, которая может быть или не быть одинаковой (поскольку котировка символов может отличаться). Это для общего случая. Но, возможно, это имело бы смысл для некоторого подмножества проблем.

Но я думаю, что для вашего конкретного случая было бы полезно указать тип как «java.lang.Object», так как это должно работать нормально: для сериализации строка будет выводиться как есть, а для десериализации она десериализуется как карта. На самом деле, возможно, вы захотите иметь отдельный геттер / сеттер; getter возвращает String для сериализации (и нуждается в @JsonRawValue); и сеттер возьмет либо карту, либо объект. Вы можете перекодировать его в String, если это имеет смысл.

46
ответ дан StaxMan 25 August 2018 в 03:31
поделиться

@JsonSetter может помочь. См. Мой пример («данные» должны содержать unparsed JSON):

class Purchase
{
    String data;

    @JsonProperty("signature")
    String signature;

    @JsonSetter("data")
    void setData(JsonNode data)
    {
        this.data = data.toString();
    }
}
14
ответ дан anagaf 25 August 2018 в 03:31
поделиться

У меня была аналогичная проблема, но с использованием списка с большим количеством JSON itens (List<String>).

public class Errors {
    private Integer status;
    private List<String> jsons;
}

Мне удалось сериализовать, используя аннотацию @JsonRawValue. Но для десериализации мне пришлось создать собственный десериализатор, основанный на предложении Роя.

public class Errors {

    private Integer status;

    @JsonRawValue
    @JsonDeserialize(using = JsonListPassThroughDeserialzier.class)
    private List<String> jsons;

}

Ниже вы можете увидеть мой десериализатор «Список».

public class JsonListPassThroughDeserializer extends JsonDeserializer<List<String>> {

    @Override
    public List<String> deserialize(JsonParser jp, DeserializationContext cxt) throws IOException, JsonProcessingException {
        if (jp.getCurrentToken() == JsonToken.START_ARRAY) {
            final List<String> list = new ArrayList<>();
            while (jp.nextToken() != JsonToken.END_ARRAY) {
                list.add(jp.getCodec().readTree(jp).toString());
            }
            return list;
        }
        throw cxt.instantiationException(List.class, "Expected Json list");
    }
}
1
ответ дан Biga 25 August 2018 в 03:31
поделиться

У меня была такая же проблема. Я нашел решение в этом сообщении: Разделите дерево JSON на простой класс с использованием Джексона или его альтернатив

Проверьте последний ответ. Определив настраиваемый параметр для свойства, которое принимает параметр JsonNode в качестве параметра и вызывает метод toString в jsonNode для установки свойства String, все это работает.

45
ответ дан Community 25 August 2018 в 03:31
поделиться

Это даже работает в сущности JPA:

private String json;

@JsonRawValue
public String getJson() {
    return json;
}

public void setJson(final String json) {
    this.json = json;
}

@JsonProperty(value = "json")
public void setJsonRaw(JsonNode jsonNode) {
    setJson(jsonNode.toString());
}
4
ответ дан Georg 25 August 2018 в 03:31
поделиться

Вот полный рабочий пример того, как использовать модули Jackson для работы @JsonRawValue в обоих направлениях (сериализация и десериализация):

public class JsonRawValueDeserializerModule extends SimpleModule {

    public JsonRawValueDeserializerModule() {
        setDeserializerModifier(new JsonRawValueDeserializerModifier());
    }

    private static class JsonRawValueDeserializerModifier extends BeanDeserializerModifier {
        @Override
        public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) {
            builder.getProperties().forEachRemaining(property -> {
                if (property.getAnnotation(JsonRawValue.class) != null) {
                    builder.addOrReplaceProperty(property.withValueDeserializer(JsonRawValueDeserializer.INSTANCE), true);
                }
            });
            return builder;
        }
    }

    private static class JsonRawValueDeserializer extends JsonDeserializer<String> {
        private static final JsonDeserializer<String> INSTANCE = new JsonRawValueDeserializer();

        @Override
        public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            return p.readValueAsTree().toString();
        }
    }
}

Затем вы можете зарегистрировать модуль после создания ObjectMapper:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new JsonRawValueDeserializerModule());

String json = "{\"foo\":\"one\",\"bar\":{\"A\":false}}";
Pojo deserialized = objectMapper.readValue(json, Pojo.class);
1
ответ дан Helder Pereira 25 August 2018 в 03:31
поделиться

Это легкое решение сработало для меня:

public class MyObject {
    private Object rawJsonValue;

    public Object getRawJsonValue() {
        return rawJsonValue;
    }

    public void setRawJsonValue(Object rawJsonValue) {
        this.rawJsonValue = rawJsonValue;
    }
}

Таким образом, я смог сохранить исходное значение JSON в переменной rawJsonValue, и тогда не было никакой проблемы десериализовать его (как объект) с другими полями назад к JSON и отправить через мой REST. Использование @JsonRawValue мне не помогло, потому что сохраненный JSON был десериализован как String, а не как объект, и это было не то, что я хотел.

2
ответ дан Pavol Golias 25 August 2018 в 03:31
поделиться

Это проблема с вашими внутренними классами. Класс Pojo является [статическим внутренним классом нестатического класса вашего тестового класса, и Джексон не может создать экземпляр этого класса. Таким образом, он может сериализоваться, но не десериализоваться.

Переопределить свой класс следующим образом:

public static class Pojo {
    public String foo;

    @JsonRawValue
    public String bar;
}

Обратите внимание на добавление static

3
ответ дан skaffman 25 August 2018 в 03:31
поделиться

Использование объекта отлично работает в обоих направлениях ... Этот метод имеет немного избыточного десериализации исходного значения в два раза.

ObjectMapper mapper = new ObjectMapper();
RawJsonValue value = new RawJsonValue();
value.setRawValue(new RawHello(){{this.data = "universe...";}});
String json = mapper.writeValueAsString(value);
System.out.println(json);
RawJsonValue result = mapper.readValue(json, RawJsonValue.class);
json = mapper.writeValueAsString(result.getRawValue());
System.out.println(json);
RawHello hello = mapper.readValue(json, RawHello.class);
System.out.println(hello.data);

RawHello.java

public class RawHello {

    public String data;
}

RawJsonValue.java

public class RawJsonValue {

    private Object rawValue;

    public Object getRawValue() {
        return rawValue;
    }

    public void setRawValue(Object value) {
        this.rawValue = value;
    }
}
1
ответ дан Vozzie 25 August 2018 в 03:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: