具有 2 个成员变量的元组作为唯一 ID 的对象列表的转换器
Converter for list of objects that have as unique id a tuple of 2 member variables
我正在尝试将 list of objects
映射到 <p:selectOneMenu
(代码如下所示):
Attribute.java
public class Attribute implements Serializable {
private String name;
private String type;
private String value; //getters setters constructors ommitted
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Attribute attribute = (Attribute) o;
return Objects.equals(name, attribute.name) &&
Objects.equals(type, attribute.type);
}
@Override
public int hashCode() {
return Objects.hash(name, type, value);
}
p:selectOneMenu 代码
<p:selectOneMenu label="Existing Attributes" value="#{cellBean.selectedAttributeFromExistings}"
converter="attrConverter">
<f:selectItem itemLabel="Existing attribute" itemValue="#{null}" itemDisabled="true"/>
<f:selectItems value="#{cellBean.allAttributes}" var="attr" itemLabel="#{attr.name}" itemValue="#{attr}"/>
<p:ajax event="change" update="@form" process="@form"/>
</p:selectOneMenu>
属性转换器(attrConverter)代码
@FacesConverter(forClass=Attribute.class, value = "attrConverter")
public class AttributeConverter implements Converter {
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String type = s.substring(s.indexOf(":") + 2, s.indexOf(","));
String name = s.substring(s.indexOf("name: ") + 6 , s.length());
Attribute attribute = new Attribute(type, name);
return attribute;
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
if(attr == null) {
return null;
}
else{
Attribute attribute = new Attribute();
String s = "";
Iterator iterator = ((LinkedTreeMap)attr).keySet().iterator();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = (String) ((LinkedTreeMap)attr).get(key);
if(key.equals("name")){
attribute.setName(value);
}
else if(key.equals("type")){
attribute.setType(value);
}
}
return attribute.toString();
}
}
但是,当我从下拉菜单中选择一个值时,出现以下异常
Validation Error: Value is not valid : Validation Error: Value is not valid
随后屏幕右上角出现错误消息/弹出消息,知道我做错了什么吗?
PS: 我见过很多例子,他们使用 unique id
来通过 [=16 中的 DTO 检索对象=] 方法,在我的示例中 Attribute
对象的 uniqueness
是 type && value
成员变量的组合。
在此先感谢您的帮助:)
我不知道为什么要将attr 投射到LinkedTreeMap
,你需要将它投射到Attribute
class。所以你的转换器 class 应该是:
@FacesConverter(forClass=Attribute.class, value = "attrConverter")
public class AttributeConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0 && !value.isEmpty()) {
/*I take your bean as ViewScoped */
CellBean cellBean = (CellBean) context.getViewRoot().getViewMap().get("cellBean");
for(Attribute a : cellBean.getAllAttributes()){
String combined = a.getType()+a.getValue();
if(combined.equals(value)){
return a;
}
}
}
return null;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value != null) {
Attribute a = (Attribute) value;
return a.getType()+a.getValue();
}
return null;
}
}
更新
面向提问者:
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String[] typeAndName = s.split("#");
return new Attribute(typeAndName[0], typeAndName[1]);
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
if(attr == null) {
return null;
}
else{
/* I assume your type and name don't contain '#' charachter */
return ((Attribute)attr).getType()+"#"+((Attribute)attr).getName();
}
}
问题的根源是我使用 gson
进行了错误的序列化,我将 Attribute
对象转换为 LinkedTreeMap
,这也是评论部分中提到的不一致。当我正确地进行序列化时,getAsObject
和 getAsString
函数具有以下形式:
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String type = s.substring(s.indexOf("type=") + 5, s.indexOf(" "));
String name = s.substring(s.indexOf("name=") + 5 , s.length());
Attribute attribute = new Attribute(type, name);
return attribute;
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
if(attr == null) {
return null;
}
else{
return "type="+((Attribute)attr).getType()+" name="+((Attribute)attr).getName();
}
}
我正在尝试将 list of objects
映射到 <p:selectOneMenu
(代码如下所示):
Attribute.java
public class Attribute implements Serializable {
private String name;
private String type;
private String value; //getters setters constructors ommitted
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Attribute attribute = (Attribute) o;
return Objects.equals(name, attribute.name) &&
Objects.equals(type, attribute.type);
}
@Override
public int hashCode() {
return Objects.hash(name, type, value);
}
p:selectOneMenu 代码
<p:selectOneMenu label="Existing Attributes" value="#{cellBean.selectedAttributeFromExistings}"
converter="attrConverter">
<f:selectItem itemLabel="Existing attribute" itemValue="#{null}" itemDisabled="true"/>
<f:selectItems value="#{cellBean.allAttributes}" var="attr" itemLabel="#{attr.name}" itemValue="#{attr}"/>
<p:ajax event="change" update="@form" process="@form"/>
</p:selectOneMenu>
属性转换器(attrConverter)代码
@FacesConverter(forClass=Attribute.class, value = "attrConverter")
public class AttributeConverter implements Converter {
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String type = s.substring(s.indexOf(":") + 2, s.indexOf(","));
String name = s.substring(s.indexOf("name: ") + 6 , s.length());
Attribute attribute = new Attribute(type, name);
return attribute;
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
if(attr == null) {
return null;
}
else{
Attribute attribute = new Attribute();
String s = "";
Iterator iterator = ((LinkedTreeMap)attr).keySet().iterator();
while(iterator.hasNext()){
String key = (String) iterator.next();
String value = (String) ((LinkedTreeMap)attr).get(key);
if(key.equals("name")){
attribute.setName(value);
}
else if(key.equals("type")){
attribute.setType(value);
}
}
return attribute.toString();
}
}
但是,当我从下拉菜单中选择一个值时,出现以下异常
Validation Error: Value is not valid : Validation Error: Value is not valid
随后屏幕右上角出现错误消息/弹出消息,知道我做错了什么吗?
PS: 我见过很多例子,他们使用 unique id
来通过 [=16 中的 DTO 检索对象=] 方法,在我的示例中 Attribute
对象的 uniqueness
是 type && value
成员变量的组合。
在此先感谢您的帮助:)
我不知道为什么要将attr 投射到LinkedTreeMap
,你需要将它投射到Attribute
class。所以你的转换器 class 应该是:
@FacesConverter(forClass=Attribute.class, value = "attrConverter")
public class AttributeConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (value != null && value.trim().length() > 0 && !value.isEmpty()) {
/*I take your bean as ViewScoped */
CellBean cellBean = (CellBean) context.getViewRoot().getViewMap().get("cellBean");
for(Attribute a : cellBean.getAllAttributes()){
String combined = a.getType()+a.getValue();
if(combined.equals(value)){
return a;
}
}
}
return null;
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value != null) {
Attribute a = (Attribute) value;
return a.getType()+a.getValue();
}
return null;
}
}
更新
面向提问者:
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String[] typeAndName = s.split("#");
return new Attribute(typeAndName[0], typeAndName[1]);
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
if(attr == null) {
return null;
}
else{
/* I assume your type and name don't contain '#' charachter */
return ((Attribute)attr).getType()+"#"+((Attribute)attr).getName();
}
}
问题的根源是我使用 gson
进行了错误的序列化,我将 Attribute
对象转换为 LinkedTreeMap
,这也是评论部分中提到的不一致。当我正确地进行序列化时,getAsObject
和 getAsString
函数具有以下形式:
@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
String type = s.substring(s.indexOf("type=") + 5, s.indexOf(" "));
String name = s.substring(s.indexOf("name=") + 5 , s.length());
Attribute attribute = new Attribute(type, name);
return attribute;
}
@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
if(attr == null) {
return null;
}
else{
return "type="+((Attribute)attr).getType()+" name="+((Attribute)attr).getName();
}
}