天道酬勤,学无止境

地图列表使用 Mapstruct 从 Java POJO 到 Protobuf (proto3)(Map List<String> with Mapstruct from Java POJO to Protobuf (proto3))

问题

我正在尝试将一些 POJO 从 Java 映射到 Protobuf (proto3)。 其中一些包含列表。 虽然使用 POJO(例如 List)映射列表没有问题,但我得到了 UnsupportedOperationException。

List<Product>示例(这工作正确):

ProductProtobuf.Builder map(Product product);

@Mapping(target = "productsList", source = "products")
ResponseProtobuf.Builder map(Response response);

List<String>示例(这不起作用):

@Mapping(target = "usersList", source = "users")
ResponseProtobuf.Builder map(Response response);

此外,我有一些用于构建器的 Mapper:

public ResponseProtobuf.Builder responseBuilder() {
    return ResponseProtobuf.newBuilder();
}

public ProductProtobuf build(ProductProtobuf.Builder builder) {
    return builder.build();
}
回答1

问题是 MapStruct 将使用getProductsList().addAll() 。 为了避免这种情况,您应该使用CollectionMappingStrategy.ADDER_PREFERRED collectionMappingStrategy 。 查看 mapstruct 示例 repo 中 mapstruct-protobuf3 中的 UserMapper。

简而言之,您需要添加:

@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
    nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)

给你的映射器。

关于您的构建器的一个信息,如果您使用的是 1.3.0.Beta1,您将不需要它,因为 MapStruct 现在已经提供了开箱即用的支持。

注意: MapStruct 中有一个错误,无法与ProtocolStringList一起正常工作。 此错误已在 1.3.0.Beta1 中修复。 如果您尝试使用此版本,它应该可以工作(如果您的productListString

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Map List<String> with Mapstruct from Java POJO to Protobuf (proto3)
    I'm trying to map some POJOs from Java to Protobuf (proto3). Some of them contain Lists. While mapping lists with POJOs (for example List) is no problem, I'm getting a UnsupportedOperationException. Example with List<Product> (this works corrctly): ProductProtobuf.Builder map(Product product); @Mapping(target = "productsList", source = "products") ResponseProtobuf.Builder map(Response response); Example with List<String> (this doesn't work): @Mapping(target = "usersList", source = "users") ResponseProtobuf.Builder map(Response response); Additionally, I have some Mapper for builder: public
  • Protobuf3:如何描述重复字符串的映射?(Protobuf3: How to describe map of repeated string?)
    问题 关于地图类型的官方文档说: map<key_type, value_type> map_field = N; ...其中 key_type 可以是任何整数或字符串类型(因此,除了浮点类型和字节之外的任何标量类型)。 value_type 可以是任何类型。 我想定义一个map<string, repeated string>字段,但它在我的libprotoc 3.0.0上似乎是非法的,它抱怨Expected ">" 。 所以我想知道是否有任何方法可以将重复的字符串放入地图中。 一个可能的解决方法可能是: message ListOfString { repeated string value = 1; } // Then define: map<string, ListOfString> mapToRepeatedString = 1; 但是这里的ListOfString看起来是多余的。 回答1 我有同样的需求,并得到了同样的错误。 我不相信这是可能的。 这是语言规范中的相关 BNF 定义。 https://developers.google.com/protocol-buffers/docs/reference/proto3-spec messageType = [ "." ] { ident "." } messageName mapField = "map" "<"
  • 必须为现有的 proto 包括 Map 创建 java pojo(have to create java pojo for the existing proto includes Map)
    问题 我曾尝试将 proto 转换为 java pojo 。 但得到了错误 [Stderr] Order.proto:12:18:应为“必需”、“可选”或“重复”。 [Stderr] Order.proto:12:21:预期的字段名称。 optional int32 orderID = 1; optional int32 quantity = 2; map<string,string> map_field = 4; repeated string product = 3; 请帮助我需要更改的内容。 我在谷歌 protobuf 开发者网站 https://developers.google.com/protocol-buffers/docs/proto#maps 上搜索它说地图字段不能重复、可选或必需 请帮我解决这个问题。 回答1 Maps 是 protobuf 3.0(又名“proto3”)中的一个新特性,它仍处于 alpha 阶段。 您可能使用的是 2.x,在这种情况下没有映射。 最好的办法是使用重复字段: repeated MyMap map_field = 4; message MyMap { optional string key = 1; optional string value = 2; }
  • SpringBoot + GoogleProtobuf
    SpringBoot + GoogleProtobuf 项目地址: protobuf-simple :https://github.com/Cyanss/protobuf-simple 一、环境配置   protobuf-java版本的选择需要对应到C++等其他端的版本以及Maven中protobuf-java版本。这里选择3.4.0版本进行演示及测试。 电脑系统: Windows 10 x64 bit protobuf GitHub: https://github.com/protocolbuffers/protobuf protobuf 源码下载: protobuf-java-3.4.0.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.4.0/protobuf-java-3.4.0.zip protoc 编译器下载: protoc-3.4.0-win32.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.4.0/protoc-3.4.0-win32.zip 注:protoc编译器3.4.0版本只有32位安装包。 protobuf-java 依赖: <dependency> <groupId>com
  • MapStruct:从 java.util.Map 映射到 Bean?(MapStruct: mapping from java.util.Map to Bean?)
    问题 我目前有一个Map<String, String> ,其中包含key = value形式的key = value ,我想将它们“扩展”为一个真实的对象。 是否可以使用 MapStruct 自动执行此操作,我将如何执行此操作? 澄清一下:我手工编写的代码如下所示: public MyEntity mapToEntity(final Map<String, String> parameters) { final MyEntity result = new MyEntity(); result.setNote(parameters.get("note")); result.setDate(convertStringToDate(parameters.get("date"))); result.setCustomer(mapIdToCustomer(parameters.get("customerId"))); // ... return result; } 回答1 方法一 MapStruct 存储库为我们提供了有用的示例,例如从地图映射。 从 java.util.Map 映射 bean 看起来像: @Mapper(uses = MappingUtil.class ) public interface SourceTargetMapper { SourceTargetMapper
  • gRPC快速入门(一)——Protobuf简介
    gRPC快速入门(一)——Protobuf简介 一、Protobuf简介 1、Protobuf简介 Protobuf即Protocol Buffers,是Google公司开发的一种跨语言和平台的序列化数据结构的方式,是一个灵活的、高效的用于序列化数据的协议。与XML和JSON格式相比,protobuf更小、更快、更便捷。protobuf是跨语言的,并且自带一个编译器(protoc),只需要用protoc进行编译,就可以编译成Java、Python、C++、C#、Go等多种语言代码,然后可以直接使用,不需要再写其它代码,自带有解析的代码。只需要将要被序列化的结构化数据定义一次(在.proto文件定义),便可以使用特别生成的源代码(使用protobuf提供的生成工具)轻松的使用不同的数据流完成对结构数据的读写操作。甚至可以更新.proto文件中对数据结构的定义而不会破坏依赖旧格式编译出来的程序。GitHub地址:https://github.com/protocolbuffers/protobuf不同语言源码版本下载地址:https://github.com/protocolbuffers/protobuf/releases/latest 2、Protobuf的优缺点 Protobuf的优点如下:A、性能号,效率高序列化后字节占用空间比XML少3-10倍,序列化的时间效率比XML快20
  • 重新开始---sgg-netty----8
    总结: 1.channelHandlerContext 2.channelOption 3.EvevtLoopGroup和NioEventLoopGroup 4.Unpooled是netty提供的自带指针不用flip,readIndex和writeIndex -----------------------------------------72--------------------------------------------- -----------------------------------------73--------------------------------------------- 问题对象是如何编解码的呢? Protobuf 目前很多公司是tcp+Protobuf替换http+json -----------------------------------------74--------------------------------------------- 代码: 第一步:引入jar包,写.protoc文件 可以看下官网的protobuf的类型 syntax = "proto3"; //版本 option java_outer_classname = "StudentPOJO";//生成的外部类名,同时也是文件名 //protobuf
  • 使用 MapStruct 进行转换时防止循环引用(Prevent Cyclic references when converting with MapStruct)
    问题 今天我开始使用 MapStruct 为我的项目创建模型到 DTO 转换器,我想知道它是否会自动处理循环引用,但事实证明它没有。 这是我用来测试它的转换器: package it.cdc.snp.services.rest.giudizio; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; import org.springframework.stereotype.Component; import it.cdc.snp.dto.entita.Avvisinotifica; import it.cdc.snp.dto.entita.Corrispondenza; import it.cdc.snp.model.notifica.AvvisoDiNotificaModel; import it.cdc.snp.model.notifica.NotificaModel; import it.cdc.snp.model.procedimento.ProcedimentoModel; @Component @Mapper(componentModel="spring")
  • 从 HashMap 条目列表中删除重复项(Remove Duplicates from List of HashMap Entries)
    问题 我有一个List<HashMap<String,Object>>代表一个数据库,其中每个列表记录都是一个数据库行。 我的数据库中有 10 列。 有几行的 2 个特定列的值相等。 在使用数据库中的所有行更新列表后,我需要从列表中删除重复项。 什么是有效的方法? 仅供参考 - 我在查询数据库时无法执行不同的操作,因为在加载数据库后,GroupName 会在稍后阶段添加到Map 。 由于 Id 列不是主键,因此一旦将 GroupName 添加到Map 。 您将有基于 Id + GroupName 组合的重复项! 希望我的问题有意义。 如果我们需要更多说明,请告诉我。 回答1 创建一个比较 HashMap 的 Comparator,并通过比较您感兴趣的键/值对来比较它们。 使用Collections.sort(yourlist, yourcomparator) ; 现在,基于您的比较器,所有彼此相似的地图在列表中都是相邻的。 创建一个新列表。 遍历您的第一个列表,跟踪您最后看到的内容。 如果当前值与上一个不同,请将其添加到新列表中。 根据您的比较器,您的新列表不应包含重复项。 遍历列表的成本是 O(n)。 排序是 O(n log n)。 所以这个算法是 O(n log n)。 我们还可以通过使用带有该比较器的 TreeSet 进行动态排序。 插入是 O(log n)。
  • Protobuf3语言指南
    定义一个消息类型 指定字段类型分配标识号指定字段规则添加更多消息类型添加注释保留标识符(Reserved)从.proto文件生成了什么?标量数值类型默认值枚举使用其他消息类型 导入定义使用proto2消息类型嵌套类型更新一个消息类型AnyOneof 使用OneofOneof 特性向后兼容性问题映射(Maps) 向后兼容性问题包(Packages) 包及名称的解析定义服务JSON 映射选项 自定义选项生成你的类 英文原文: Language Guide (proto3) 中文出处: Protobuf语言指南 [译]Protobuf 语法指南 中文出处是proto2的译文,proto3的英文出现后在原来基础上增改了,水平有限,还请指正 这个指南描述了如何使用Protocol buffer 语言去描述你的protocol buffer 数据, 包括 .proto文件符号和如何从.proto文件生成类。包含了proto2版本的protocol buffer语言:对于老版本的proto3 符号,请见Proto2 Language Guide(以及中文译本,抄了很多这里的感谢下老版本的翻译者) 本文是一个参考指南——如果要查看如何使用本文中描述的多个特性的循序渐进的例子,请在教程中查找需要的语言的教程。 定义一个消息类型 先来看一个非常简单的例子。假设你想定义一个“搜索请求”的消息格式
  • MapStruct 可以对 Hibernate 实体类进行深度代理吗(Can MapStruct do a deep deproxy of Hibernate Entity Classes)
    问题 对于想要直接返回实体类的 Web 服务开发人员来说,这是一个常见问题。 即使我需要的所有数据都已加载,仍有许多我不需要的未初始化代理和集合。 我希望他们只返回 null 而不是抛出延迟加载异常。 基本上我只想要 POJO 合同,但是必须清除代理和休眠集合才能获得它(除非休眠中有一些我不知道的新方法)。 我可以使用 MapStruct 来做到这一点吗? 如果需要,有关此的更多详细信息: http://www.mojavelinux.com/blog/archives/2006/06/hibernate_get_out_of_my_pojo/ http://www.gwtproject.org/articles/using_gwt_with_hibernate.html 吉利德是我发现的唯一适用于此的东西,但它已经不复存在了。 回答1 是的,您可以使用 MapStruct 做到这一点。 但是,只有通过明确标记要映射的内容和要忽略的内容。 假设您有以下课程: public class Car { private String name; private int year; //This is lazy loaded private List<Wheel> wheels; //getters and setters omitted for simplicity } public
  • Java 8 Lambdas组列表进入地图(Java 8 lambdas group list into map)
    问题 我想获取一个List<Pojo>并return一个Map<String, List<Pojo>> ,其中Map的键是Pojo的String值,我们称它为String key 。 为了澄清,给出以下内容: Pojo 1:键:a值:1 Pojo 2:键:a值:2 Pojo 3:键:b值:3 Pojo 4:键:b值:4 我想要一个Map<String, List<Pojo>> ,其keySet()大小为2,其中键“ a”具有Pojos 1和2,键“ b”具有pojos 3和4。 如何使用Java 8 lambda达到最佳效果? 回答1 看来,您需要的是简单的groupingBy变体: Map<String, List<Pojo>> map = pojos.stream().collect(Collectors.groupingBy(Pojo::getKey)); 回答2 另外,如果您想返回一个相似的地图,而不是整个Pojo,而是希望地图的值是Pojo的某些属性,则可以这样做: Map<String, List<String>> map = pojos.stream() .collect( Collectors.groupingBy( Employee::getKey, Collectors.mapping( Pojo::getSomeStringProperty
  • [翻译] ProtoBuf 官方文档(二)- 语法指引(proto2)
    以下内容转载自 https://www.jianshu.com/p/6f68fb2c7d19 翻译查阅外网资料过程中遇到的比较优秀的文章和资料,一是作为技术参考以便日后查阅,二是训练英文能力。 此文翻译自 Protocol Buffers 官方文档 Language Guide 部分 翻译为意译,不会照本宣科的字字对照翻译 以下为原文内容翻译 语法指引(proto2) 本指南介绍如何使用 protocol buffer 语言来构造 protocol buffer 数据,包括 .proto 文件语法以及如何从 .proto 文件生成数据访问类。它涵盖了 protocol buffer 语言的 proto2 版本:有关较新的 proto3 语法的信息,请参阅 Proto3 语法指引。 这是一个参考指南,有关使用本文档中描述的许多功能的分步示例,请参阅各种语言对应的具体 教程。 定义一个 Message 类型 首先让我们看一个非常简单的例子。假设你要定义一个搜索请求的 message 格式,其中每个搜索请求都有一个查询字符串,你感兴趣的特定结果页数(第几页)以及每页的结果数。下面就是定义这个请求的 .proto 文件: message SearchRequest { required string query = 1; // 查询字符串 optional int32 page
  • [翻译]ProtoBuf 官方文档(二)- 语法指引(proto2)
    翻译查阅外网资料过程中遇到的比较优秀的文章和资料,一是作为技术参考以便日后查阅,二是训练英文能力。 此文翻译自 Protocol Buffers 官方文档 Language Guide 部分 翻译为意译,不会照本宣科的字字对照翻译 以下为原文内容翻译 语法指引(proto2) 本指南介绍如何使用 protocol buffer 语言来构造 protocol buffer 数据,包括 .proto 文件语法以及如何从 .proto 文件生成数据访问类。它涵盖了 protocol buffer 语言的 proto2 版本:有关较新的 proto3 语法的信息,请参阅 Proto3 语法指引。 这是一个参考指南,有关使用本文档中描述的许多功能的分步示例,请参阅各种语言对应的具体 教程。 定义一个 Message 类型 首先让我们看一个非常简单的例子。假设你要定义一个搜索请求的 message 格式,其中每个搜索请求都有一个查询字符串,你感兴趣的特定结果页数(第几页)以及每页的结果数。下面就是定义这个请求的 .proto 文件: message SearchRequest { required string query = 1; // 查询字符串 optional int32 page_number = 2; // 第几页 optional int32 result_per_page =
  • 从 arrayList 中检索 MapStruct(MapStruct Retrieving from arrayList)
    问题 我正在尝试使用 MapStruct 来映射两个对象。 我一直在寻找一段时间,但我一直找不到任何东西,尽管我是编程新手,所以我确信它比我制作它更容易。 这是一些剥离的代码(请注意,实际代码更复杂,来自 arraylist 的子对象与此处的目标对象子变量的类型不同): 源对象 public class SourceObject { public ArrayList<ListObject> list = new ArrayList<ListObject>(); public SourceObject() { list.add(new ListObject()); } } 列表对象 public class ListObject { public DetailsObject details = new DetailsObject(); public ListObject() { details.forename="SourceForename"; details.surname="SourceSurname"; } } 目标对象 public class DestinationObject { public DetailsObject details = new DetailsObject(); public DestinationObject() { details
  • 初始Netty原理(四)— 序列化
    在开发一些远程过程调用(RPC)的程序时,一般都会涉及到对象的序列化和反序列化的问题(因为TCP或UDP这些低层协议只能传输字节流,所以应用层需要将Java POJO对象序列化为字节流才能传输)。 对象的序列化方式有以下几种方式: JSON:将Java POJO对象转换成JSON结构化的字符串。一般用于Web应用和移动开发,可读性较强,性能较差。XML:与JSON一样,也是序列化为字符串,只是格式不同,可读性强,一般用于异构系统。JDK内置序列化:将Java POJO对象转换成二进制字节数组,可移植性强,性能较差,可读性差。Protobuf:类似JDK内置序列化,Google开源的高性能、易扩展框架,一般用于高性能通信。 一般常用的序列化方式就是JSON(性能要求不太高的Web开发等)和protobuf(高性能应用,比如和Netty一起实现高性能通信)。 JSON JSON序列化框架 使用的比较多的两个开源的处理JSON的类库: FastJson:这是阿里开源的一个高性能的JSON库,采用独创的算法,将JSON转为Java POJO对象的速度非常快,但将复杂的POJO转换成JSON时可能会出错。Gson:这是Google开源的一个非常完善的JSON解析库,可以完成复杂类型的POJO和JSON之间的相互转换。 结合两者的优势,一般策略是:将POJO转为JSON时使用Gson(序列化)
  • Protobuf 的 proto3 与 proto2 的区别
    转自:https://solicomo.com/network-dev/protobuf-proto3-vs-proto2.html 这是一篇学习笔记。在粗略的看了 Protobuf 的文档中关于 proto2 和 proto3 的说明后,记录下了几点 proto3 区别于 proto2 的地方。 总的来说,proto3 比 proto2 支持更多语言但 更简洁。去掉了一些复杂的语法和特性,更强调约定而弱化语法。如果是首次使用 Protobuf ,建议使用 proto3 。 在第一行非空白非注释行,必须写: syntax = “proto3”; 字段规则移除了 “required”,并把 “optional” 改名为 “singular”1; 在 proto2 中 required 也是不推荐使用的。proto3 直接从语法层面上移除了 required 规则。其实可以做的更彻底,把所有字段规则描述都撤销,原来的 repeated 改为在类型或字段名后加一对中括号。这样是不是更简洁? “repeated”字段默认采用 packed 编码; 在 proto2 中,需要明确使用 [packed=true] 来为字段指定比较紧凑的 packed 编码方式。 语言增加 Go、Ruby、JavaNano 支持; 移除了 default 选项; 在 proto2 中,可以使用 default
  • 深入 ProtoBuf - 简介Protobuf 使用指南
    简单来讲, ProtoBuf 是结构数据序列化[1] 方法,可简单类比于 XML[2],其具有以下特点: 语言无关、平台无关。即 ProtoBuf 支持 Java、C++、Python 等多种语言,支持多个平台 高效。即比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单 扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程序 序列化[1]:将结构数据或对象转换成能够被存储和传输(例如网络传输)的格式,同时应当要保证这个序列化结果在之后(可能在另一个计算环境中)能够被重建回原来的结构数据或对象。 更为详尽的介绍可参阅 维基百科。 类比于 XML[2]:这里主要指在数据通信和数据存储应用场景中序列化方面的类比,但个人认为 XML 作为一种扩展标记语言和 ProtoBuf 还是有着本质区别的。 使用 ProtoBuf 对 ProtoBuf 的基本概念有了一定了解之后,我们来看看具体该如何使用 ProtoBuf。 第一步,创建 .proto 文件,定义数据结构,如下例1所示: // 例1: 在 xxx.proto 文件中定义 Example1 message message Example1 { optional string stringVal = 1; optional bytes bytesVal = 2; message
  • protobuf语法详解
    文章目录 一、包(package)二、选项(option)三、消息类型(message)3.1、常规消息类型3.1.1、字段修饰符3.1.2、字段类型3.1.2.1、标量类型3.1.2.2、枚举类型3.1.2.3、Any类型3.1.2.4、oneof类型3.1.2.5、map类型 3.1.3、默认值说明3.1.4、标识号 3.2、多个消息类型3.3、嵌套消息类型3.4、更新消息类型 四、RPC服务(service)五、其他5.1 导入proto文件(import) 一、包(package)   为.proto文件添加package声明符,可以防止不同 .proto项目间消息类型的命名发生冲突。 package foo.bar; message Open { ... } message Foo { ... foo.bar.Open open = 1; ... } protobuf包类型的解析和C++类似,都是由内而外进行解析。对于C++,产生的类会被包装在C++的命名空间中,如上例中的Open会被封装在 foo::bar空间中。 二、选项(option)   option会影响特定环境下的处理方式,但是不会改变整个文件声明的含义。 option optimize_for = CODE_SIZE; 三、消息类型(message)   message用于定义结构数据,可以包含多种类型字段
  • MapStruct:对象的映射列表,当对象从两个对象映射时(MapStruct: Map List of objects, when object is mapped from two objects)
    问题 假设我有这样的映射: @Mapping(source = "parentId", target = "parent.id") Child map(ChildDto dto, Parent parent); 现在我需要将 ChildDto 列表映射到 Child 列表,但它们都具有相同的父级。 我希望做这样的事情: List<Child> map(List<ChildDto> dtoList, Parent parent); 但它不起作用。 有机会做到吗? 回答1 我按照 Gunnar 的建议使用了@AfterMapping : @AfterMapping public void afterDtoToEntity(final QuestionnaireDTO dto, @MappingTarget final Questionnaire entity) { entity.getQuestions().stream().forEach(question -> question.setQuestionnaire(entity)); } 这确保所有问题都链接到同一个问卷实体。 这是避免 JPA 错误的解决方案的最后一部分, save the transient instance before flushing具有子项列表的新父实体save the transient instance