gpt4 book ai didi

java - Jackson - 如何获得依赖于 View 的 CsvSchema?

转载 作者:行者123 更新时间:2023-11-30 10:25:46 25 4
gpt4 key购买 nike

我正在尝试将我的 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 公开字段 abInternal 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com