我有一个豆子类似于:
public class Product {
public String id;
public String vendor;
public Set<Image> images;
}
public class Image {
public String originalSrc;
}
我正在尝试反序列化类似于以下内容的JSON:
{
"id": "gid:\/\/mysite\/Product\/1853361520730",
"vendor": "gadgetdown",
"images": {
"edges": [
{
"node": {
"originalSrc": "https:\/\/cdn.something.com"
}
},
{
"node": {
"originalSrc": "https:\/\/cdn.something.com"
}
}
]
}
我无法反序列化该对象,因为每个图像对象都包装在节点对象中,并集中在边对象中。
编辑:为了清楚起见,我不想通过使用bean来完成这一点,这个示例是一个简化,JSON有效负载中的所有数组项都包装在这个边缘
和节点
表示中。
要将图像从节点{“originalSrc”:“https:\/\/cdn.something.com”}中展开只需使用注释
@JsonRootName(value = "node")
class Image {
public String originalSrc;
}
但将图像集合从<代码>“图像”:{“边”:[{…}中展开,{...}] } 有点复杂,需要使用自定义的JsonDeserializer
class Product {
public String id;
public String vendor;
@JsonDeserialize(using = ImageSetDeserializer.class)
public Set<Image> images;
}
class ImageSetDeserializer extends JsonDeserializer<Set<Image>> {
public Set<Image> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
ObjectMapper mapper = (ObjectMapper) jsonParser.getCodec();
JsonNode node = mapper.readTree(jsonParser);
return mapper.convertValue(node.get("edges").findValues("node"), new TypeReference<Set<Image>>() {});
}
}
最后一个测试:
public class ProductTest {
private final String source = "{\n" +
" \"id\": \"gid:\\/\\/mysite\\/Product\\/1853361520730\",\n" +
" \"vendor\": \"gadgetdown\",\n" +
" \"images\": {\n" +
" \"edges\": [\n" +
" {\n" +
" \"node\": {\n" +
" \"originalSrc\": \"https:\\/\\/cdn.something.com\"\n" +
" }\n" +
" },\n" +
" {\n" +
" \"node\": {\n" +
" \"originalSrc\": \"https:\\/\\/cdn.something.com\"\n" +
" }\n" +
" }\n" +
" ]\n" +
" }" +
"}";
@Test
public void test() throws IOException {
ObjectMapper mapper = new ObjectMapper();
Product product = mapper.readValue(source, Product.class);
assertEquals(product.id, "gid://mysite/Product/1853361520730");
assertEquals(product.vendor, "gadgetdown");
assertNotNull(product.images);
List<Image> images = new ArrayList<>(product.images);
assertEquals(images.size(), 2);
assertEquals(images.get(0).originalSrc, "https://cdn.something.com");
assertEquals(images.get(1).originalSrc, "https://cdn.something.com");
}
}
如果每个列表都有如下结构:
{
"images": {
"edges": [
{
"node": {
"entry": "entry-value"
}
}
]
}
}
每个列表都是一个具有边属性的JSON对象,数组中的每个元素都由节点属性的JSON对象包装。对于这种结构,我们可以编写类似于Jackson的通用反序列化器-将对象的内部列表反序列化为一个更高级别问题的列表。
示例设置
反序列器:
class InnerSetDeserializer extends JsonDeserializer<Set> implements ContextualDeserializer {
private final JavaType propertyType;
public InnerSetDeserializer() {
this(null);
}
public InnerSetDeserializer(JavaType propertyType) {
this.propertyType = propertyType;
}
@Override
public Set deserialize(JsonParser p, DeserializationContext context) throws IOException {
p.nextToken(); // SKIP START_OBJECT
p.nextToken(); // SKIP any FIELD_NAME
CollectionType collectionType = getCollectionType(context);
List<Map<String, Object>> list = context.readValue(p, collectionType);
p.nextToken(); // SKIP END_OBJECT
return list.stream().map(Map::values).flatMap(Collection::stream).collect(Collectors.toSet());
}
private CollectionType getCollectionType(DeserializationContext context) {
TypeFactory typeFactory = context.getTypeFactory();
MapType mapType =
typeFactory.constructMapType(
Map.class, String.class, propertyType.getContentType().getRawClass());
return typeFactory.constructCollectionType(List.class, mapType);
}
@Override
public JsonDeserializer<?> createContextual(DeserializationContext context, BeanProperty property) {
return new InnerSetDeserializer(property.getType());
}
}
我们可以使用如下:
class Product {
private String id;
private String vendor;
@JsonDeserialize(using = InnerSetDeserializer.class)
private Set<Image> images;
// getters, setters
}
示例应用程序:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class JsonApp {
public static void main(String[] args) throws IOException {
File jsonFile = new File("./resources/test.json");
ObjectMapper mapper = new ObjectMapper();
Product product = mapper.readValue(jsonFile, Product.class);
System.out.println(product);
}
}
以上代码打印:
Product{id='gid://mysite/Product/1853361520730', vendor='gadgetdown', images=[Image{originalSrc='https://cdn.something.com'}, Image{originalSrc='https://cdn.something.com'}]}
因此,图像不是一个集合,而是一个包含边缘列表的对象
public class Images {
private List<Edge> edges;
}
每个边都包含节点对象,
public class Edge {
private Node node;
}
每个节点都有单个字符串属性
public class Node {
private String originalSrc;
}
每一行中的项目将根据其文本大小而有所不同。Flatlist用于呈现项目。 TagView.js 风格 结果 但这里的项目没有用设备宽度包装。有没有包装内容物?
问题内容: 有时,使用熊猫时,我会得到一系列元组/列表。例如,在进行分组并传递具有多个返回值的函数时,这很常见: 什么是“解包”此结构的正确方法,以便获得具有两列的DataFrame? 一个相关的问题是如何将这个结构或生成的数据框解包到两个Series / array对象中。这几乎可以工作: 但这是 而且需要采取额外的措施来挤压它。 问题答案: 也许这是最愚蠢的(我猜是最pythonic): 如果
我的目标是从用户输入的“AM”-“PM”字符串格式打印包含24小时十进制格式的进入和退出时间的列表,如以下字符串数组:{6AM#8AM,11AM#1PM,7AM#8PM,7AM#8AM,10AM#12PM,12PM#4PM,1PM#4PM,8AM#9AM} 我在for循环中声明了各个列表,并在循环中为它们赋值,但从代码中得到了以下运行时异常:java。lang.IndexOutOfBoundsEx
问题内容: 这个问题已经在这里有了答案 : 循环“忘记”以删除一些项目[重复] (10个答案) 6年前关闭。 我想从列表“ a”中删除项目,其中列表“ b”包含在列表“ a”中找到带有单词的项目 结果应为: 这是因为在列表“ a”的项目中找到了单词“二”和“五六”。 这是我尝试解决的方法: 返回: 为什么这不起作用,如何解决此问题? 谢谢。 问题答案: 遍历列表时,请勿修改列表。这样做会产生不良的
问题内容: 我有一个清单清单: 搜索列表并返回其中一项的位置的最干净方法是什么? 我已经看过该方法,但是似乎并没有在列表中解压缩列表。 给出:,不是我所期望的… 问题答案: 我会做这样的事情: 这将返回一个元组列表,其中第一个索引是第一个列表中的位置,第二个索引是第二个列表中的位置(注意:您要查找的颜色,即)。 对于问题中的示例,返回值为: 如果您只需要懒惰地找到找到颜色的第一个位置,则可以使用以
问题内容: 我正在从表单文本字段,并从复选框中的字段 我将它们像这样组合: (此函数在列表中的字符串内去除空格。) 但在这种情况下是空的(没有新的标签进入),但也有一些,包含一个空字符串。 例如,来自: 我如何摆脱空字符串? 如果列表中有一个空字符串: 但是,如果没有空字符串: 但这给出了: 为什么会发生这种情况,我该如何解决? 问题答案: 1)几乎是英式风格: 使用操作员测试是否存在,然后应用该