- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试将我的 POJO 转换为 2 种不同的 CSV 表示形式。
我的 POJO:
@NoArgsConstructor
@AllArgsConstructor
public static class Example {
@JsonView(View.Public.class)
private String a;
@JsonView(View.Public.class)
private String b;
@JsonView(View.Internal.class)
private String c;
@JsonView(View.Internal.class)
private String d;
public static final class View {
interface Public {}
interface Internal extends Public {}
}
}
Public
View 公开字段 a
和 b
,Internal
View 公开所有字段。
问题是,如果我用 .writerWithSchemaFor(Example.class)
构造 ObjectWriter
,我的所有字段都包含但忽略了 View 定义的内容。 ObjectWriter
将创建由 Example.class
定义的模式,但如果我应用 .withView
它只会隐藏字段,不会忽略它们。
这意味着我必须手动构建架构。
测试:
@Test
public void testJson() throws JsonProcessingException {
final ObjectMapper mapper = new ObjectMapper();
final Example example = new Example("1", "2", "3", "4");
final String result = mapper.writerWithView(Example.View.Public.class).writeValueAsString(example);
System.out.println(result); // {"a":"1","b":"2"}
}
@Test
public void testCsv() throws JsonProcessingException {
final CsvMapper mapper = new CsvMapper();
final Example example = new Example("1", "2", "3", "4");
final String result = mapper.writerWithSchemaFor(Example.class).withView(Example.View.Public.class).writeValueAsString(example);
System.out.println(result); // 1,2,,
}
@Test
public void testCsvWithCustomSchema() throws JsonProcessingException {
final CsvMapper mapper = new CsvMapper();
CsvSchema schema = CsvSchema.builder()
.addColumn("a")
.addColumn("b")
.build();
final Example example = new Example("1", "2", "3", "4");
final String result = mapper.writer().with(schema).withView(Example.View.Public.class).writeValueAsString(example);
System.out.println(result); // 1,2
}
testCsv
测试有 4 个字段,但排除了 2 个。 testCsvWithCustomSchema
测试只有我想要的字段。
有没有办法获得与我的 @JsonView
匹配的 CsvSchema
而无需自己构建它?
最佳答案
这是我用反射做的一个解决方案,我对它不是很满意,因为它仍然是“手动”构建模式。
这个解决方案也很糟糕,因为它忽略了像 MapperFeature.DEFAULT_VIEW_INCLUSION
这样的映射器配置。
这似乎是在做一些图书馆应该已经提供的事情。
@AllArgsConstructor
public class GenericPojoCsvSchemaBuilder {
public CsvSchema build(final Class<?> type) {
return build(type, null);
}
public CsvSchema build(final Class<?> type, final Class<?> view) {
return build(CsvSchema.builder(), type, view);
}
public CsvSchema build(final CsvSchema.Builder builder, final Class<?> type) {
return build(builder, type, null);
}
public CsvSchema build(final CsvSchema.Builder builder, final Class<?> type, final Class<?> view) {
final JsonPropertyOrder propertyOrder = type.getAnnotation(JsonPropertyOrder.class);
final List<Field> fieldsForView;
// DO NOT use Arrays.asList because it uses an internal fixed length implementation which cannot use .removeAll (throws UnsupportedOperationException)
final List<Field> unorderedFields = Arrays.stream(type.getDeclaredFields()).collect(Collectors.toList());
if (propertyOrder != null && propertyOrder.value().length > 0) {
final List<Field> orderedFields = Arrays.stream(propertyOrder.value()).map(s -> {
try {
return type.getDeclaredField(s);
} catch (final NoSuchFieldException e) {
throw new IllegalArgumentException(e);
}
}).collect(Collectors.toList());
if (propertyOrder.value().length < type.getDeclaredFields().length) {
unorderedFields.removeAll(orderedFields);
orderedFields.addAll(unorderedFields);
}
fieldsForView = getJsonViewFields(orderedFields, view);
} else {
fieldsForView = getJsonViewFields(unorderedFields ,view);
}
final JsonIgnoreFieldFilter ignoreFieldFilter = new JsonIgnoreFieldFilter(type.getDeclaredAnnotation(JsonIgnoreProperties.class));
fieldsForView.forEach(field -> {
if (ignoreFieldFilter.matches(field)) {
builder.addColumn(field.getName());
}
});
return builder.build();
}
private List<Field> getJsonViewFields(final List<Field> fields, final Class<?> view) {
if (view == null) {
return fields;
}
return fields.stream()
.filter(field -> {
final JsonView jsonView = field.getAnnotation(JsonView.class);
return jsonView != null && Arrays.stream(jsonView.value()).anyMatch(candidate -> candidate.isAssignableFrom(view));
})
.collect(Collectors.toList());
}
private class JsonIgnoreFieldFilter implements ReflectionUtils.FieldFilter {
private final List<String> fieldNames;
public JsonIgnoreFieldFilter(final JsonIgnoreProperties jsonIgnoreProperties) {
if (jsonIgnoreProperties != null) {
fieldNames = Arrays.asList(jsonIgnoreProperties.value());
} else {
fieldNames = null;
}
}
@Override
public boolean matches(final Field field) {
if (fieldNames != null && fieldNames.contains(field.getName())) {
return false;
}
final JsonIgnore jsonIgnore = field.getDeclaredAnnotation(JsonIgnore.class);
return jsonIgnore == null || !jsonIgnore.value();
}
}
}
关于java - Jackson - 如何获得依赖于 View 的 CsvSchema?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45962482/
我创建了一个将在 CSVMapper.schemaFor 中使用的 Java POJO: @JsonPropertyOrder({ "mkg_brnd_id", "prnt_brnd_id" }) p
我正在尝试将我的 POJO 转换为 2 种不同的 CSV 表示形式。 我的 POJO: @NoArgsConstructor @AllArgsConstructor public static cla
我设置了一个 CsvSchema 和 CsvMapper 来读取第一行包含列名称的 CSV 文件。 我需要能够对数据进行一些处理,更改特定字段,然后在保留列顺序的同时将数据写回。我假设 CsvMapp
我是一名优秀的程序员,十分优秀!