【问题标题】:How have RecursiveToStringStyle and JSON_STYLE using commons-lang3RecursiveToStringStyle 和 JSON_STYLE 如何使用 commons-lang3
【发布时间】:2015-11-06 11:33:30
【问题描述】:

我正在使用依赖项:

    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.4</version>
    </dependency>

我有以下物品:

public Class X {

  private String a;
  private String b;
  private Y y;
}

public Class Y {
  private String c;
  private String d;
}

我需要递归地记录类 X 的内容以获取类 Y 以及使用 JSON 样式。这是我的目标,也是这个问题的目的。

方法一:

ToStringStyle style = ToStringStyle.JSON_STYLE;
LOGGER.debug(ReflectionToStringBuilder.toString(new X(), style, false, false));

方法 1 结果:

{"a":"<a>","b":"<b>","y": com.<packages>.y@<hash>}

方法二:

RecursiveToStringStyle style = new RecursiveToStringStyle();
LOGGER.debug(ReflectionToStringBuilder.toString(new X(), style, false, false));

方法2结果:

[com.<packages>.x@<hash>[a=<a>,b=<b>,y=com.<packages>.y@<hash>[c=<c>,d=<d>]]

成功的方法:

`Merge of Approach 1 and Approach 2` but how to achieve this? 

成功的方法结果(我的目标):

{"a":"<a>","b":"<b>","y":{"c":"<c>","d":"<d>"}}

【问题讨论】:

  • 听起来像是您可以提交的功能请求... 可以实现为 RecursiveToStringStyle 的子类,类似于现有的 MultilineRecursiveToStringStyle。
  • 是的,我已经尝试过这种方法。但我认为必须有更好的方法来实现我的目标。也许使用另一个依赖项?
  • 仅供参考,这个问题和这些答案似乎也适用于commons-lang3 版本3.9。

标签: java reflection tostring apache-commons-lang


【解决方案1】:

我找到了解决方案。我需要Override 每个classes 的方法toString(在这种情况下为X 和Y)

public Class X {

  private String a;
  private String b;
  private Y y;

  @Override
  public String toString() {
    return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
  }
}

public Class Y {
  private String c;
  private String d;

  @Override
  public String toString() {
    return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
  }
}

现在,使用方法 1 它正在工作。

【讨论】:

  • 当然,如果您可以更改所有相关类的toString 方法,那将有效。 ToStringBuilder 的好处是它可以是外部的。但是为什么要让事情变得比必要的复杂。
【解决方案2】:

您可以扩展 RecursiveToStringStyle 类来编写自己的样式类并设置参数以匹配 JSON_STYLE 或任何其他样式。

class CustomStyle extends RecursiveToStringStyle {

    public CustomStyle() {
        super();
        super.setUseClassName(false);
        super.setUseIdentityHashCode(false);
        super.setContentStart("{");
        super.setContentEnd("}");
        super.setArrayStart("[");
        super.setArrayEnd("]");
        super.setFieldSeparator(",");
        super.setFieldNameValueSeparator(":");
        super.setNullText("null");
        super.setSummaryObjectStartText("\"<");
        super.setSummaryObjectEndText(">\"");
        super.setSizeStartText("\"<size=");
        super.setSizeEndText(">\"");
    }
}

public class Z {
    public String objectToString(Object obj) {
        ToStringStyle style = new CustomStyle();
        return new ReflectionToStringBuilder(obj, style).toString();
    }
}

要创建自定义样式,最好查看在 ToStringStyle 类中设置的样式参数。您可以使用 setter 方法在自定义实现中自定义默认设置。

【讨论】:

  • 注意:这种方法将输出感觉像 JSON 的值,但不会解析为 JSON。特别是,它不引用字段名称或字符串值。这是因为字符串引用是作为 JsonToStringStyle 类的一部分在称为 appendValueAsString() 的方法中实现的。
【解决方案3】:

我遇到了类似的问题,因为它也只影响一个字段,所以我最终这样做了(我实际上使用 SHORT_PREFIX_STYLE,但为了举例,我将其保留为 JSON):

@Override
public String toString() {
    return (new ReflectionToStringBuilder(this, ToStringStyle.JSON_STYLE) {
        @Override
        protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
            return "y".equals(field.getName()) ?
                ReflectionToStringBuilder.toString(y, ToStringStyle.JSON_STYLE) :
                super.getValue(field);
        }
    }).toString();
}

另一个原因是我无法控制字段y 源代码。

(很遗憾ToStringStyle 的实例没有以某种可组合的方式设计。我认为递归根本不是“风格”的一部分,它是应该独立建模的遍历的一个方面)

【讨论】:

    猜你喜欢
    • 2017-09-16
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2015-05-22
    • 1970-01-01
    • 2018-04-04
    • 1970-01-01
    • 2016-03-30
    相关资源
    最近更新 更多