[英]how to make java class behave like a normal object and list-of-object at runtime and as per need?
我在 java 中有一個簡單的 class,如下所示:
class Simple {
private String name;
private String email;
}
根據我的程序接收到的輸入數據,我想要java.util.List<Simple>
和Simple
的行為。
IE
情況 1:: 如果我的程序收到以下類型的 json 數組輸入
{"simple" : [ {"name":"a", "email" : "a@z.com"}, {"name":"b", "email" : "b@z.com"} ]}
我需要使用List<Simple>解析它
情況 2:: 如果我的程序收到以下類型的 json 對象輸入
{"simple" : {"name":"c", "email" : "c@z.com"} }
我需要使用Simple解析它
注意:我試過使用JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY
,但問題是它基本上是在編寫 json 時將單個值也轉換為 json 數組。我需要按原樣堅持 json,有沒有其他方法可以實現這個?
您可以使用JsonNode.isArray()
(或JsonNode.isObject()
)來執行此檢查。
然后您可以使用ObjectReader.readValue()
將節點解析為列表或使用ObjectMapper.treeToValue()
解析為 POJO。
String myJson = """
{"simple" : {"name":"c", "email" : "c@z.com"} }
""";
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(myJson);
if (node.isArray()) {
ObjectReader reader = mapper.readerFor(new TypeReference<List<Simple>>() {});
List<Simple> list = reader.readValue(node);
// do something with a list
} else {
Simple pojo = mapper.treeToValue(node, Simple.class);
// do something else with a single object
}
為了避免任何Jackson
自定義,我將創建包裝器 class 和一個Object simple
屬性。 我們可以添加兩個額外的檢查方法和兩個額外的轉換方法。 它將允許Jackson
執行它的邏輯,在運行時我們可以檢查我們實際擁有的內容:
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Collections;
import java.util.List;
public class DateApp {
private final static JsonMapper JSON_MAPPER = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).build();
public static void main(String[] args) throws Exception {
Simple object = new Simple("John", "john@doe.com");
SimpleWrapper wrapper = new SimpleWrapper();
wrapper.setSimple(object);
serializeAndDeserialize(wrapper);
wrapper.setSimple(Collections.singletonList(object));
serializeAndDeserialize(wrapper);
}
private static void serializeAndDeserialize(SimpleWrapper wrapper) throws JsonProcessingException {
String json = JSON_MAPPER.writeValueAsString(wrapper);
System.out.println("JSON:");
System.out.println(json);
wrapper = JSON_MAPPER.readValue(json, SimpleWrapper.class);
System.out.println("Wrapper:");
System.out.println(wrapper);
}
}
@Data
class SimpleWrapper {
private Object simple;
@JsonIgnore
public boolean isSimpleObject() {
return simple instanceof Simple;
}
@JsonIgnore
public boolean isSimpleList() {
return simple instanceof List;
}
@JsonIgnore
public Simple getSimpleAsObject() {
return (Simple) simple;
}
@JsonIgnore
public List<Simple> getSimpleAsList() {
return (List<Simple>) simple;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
class Simple {
private String name;
private String email;
}
上面的代碼打印:
JSON:
{
"simple" : {
"name" : "John",
"email" : "john@doe.com"
}
}
Wrapper:
SimpleWrapper(simple={name=John, email=john@doe.com})
JSON:
{
"simple" : [ {
"name" : "John",
"email" : "john@doe.com"
} ]
}
Wrapper:
SimpleWrapper(simple=[{name=John, email=john@doe.com}])
Jackson 能夠將任何 json 解析為 map,其中值是任何 object。然后您可以查詢 map 值的類型
Map<String, Object> map = new ObjectMapper().readValue(jsonInput, Map.class);
Object value = map.get("simple");
if (value instanceof Collection) { // will return false for null
Collection<Simple> simples = (Collection<Simple>)value;
}
else if (value instanceof Simple) {
Simple simple = (Simple)value;
}
else {
System.err.println("unrecognized");
}
您只需要讀取第一個節點, simple
並檢查它是否是一個數組 - 使用isArray()
方法。
public class Main{
public static void main(String args[]) {
//String inputString = [your input];
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(inputString);
JsonNode simpleNode = root.findPath("simple");
if(simpleNode.isArray()) {
//you have an array
} else {
// you have an element
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.