【问题标题】:Converting Java object to JSON with specific syntax使用特定语法将 Java 对象转换为 JSON
【发布时间】:2016-04-01 08:50:08
【问题描述】:

我想将 Java 对象转换为 JSON 字符串。假设对象看起来像这样:

public class User{
    private Long id;
    private String firstName;
}

json 应该是这样的:

{
    "inputFields":[
        {
            "name":"id",
            "value":"123"
        },
        {
            "name":"firstName",
            "value":"George"
        }
    ]
}

尝试使用 Jackson,但它似乎不提供这种序列化。

【问题讨论】:

  • 你需要自定义序列化器来SerializeUser对象的数组。
  • 为什么需要这么笨拙的 JSON 结构?有"id":"123","name":"George"不是更好吗?
  • 你可能想看看这个线程 - How to serialize Object to JSON?
  • @BadCash,总是有原因的。对于这种情况,我正在尝试与外部 WebService 集成,它需要这样的结构。

标签: java json serialization


【解决方案1】:

Jackson 可以使用自定义序列化程序,您可以在其中控制生成输出。 以下是执行此操作的步骤:

注释您的 POJO 以使用自定义序列化程序

@JsonSerialize(using = CustomSerializer.class)
static class User{
    public Long id;
    public String firstName;

    public User(Long id, String firstName) {
        this.id = id;
        this.firstName = firstName;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
}

声明序列化器

static class CustomSerializer extends JsonSerializer{

    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        jgen.writeStartObject();
        jgen.writeArrayFieldStart("inputFields");

        Field[] fields = value.getClass().getDeclaredFields();

        for (Field field : fields) {
            try {
                field.setAccessible(true);
                jgen.writeStartObject();
                jgen.writeObjectField("name", field.getName());
                jgen.writeObjectField("value", field.get(value));
                jgen.writeEndObject();
            } catch (IllegalArgumentException | IllegalAccessException e) {
                e.printStackTrace();
            }

        }

        jgen.writeEndArray();
        jgen.writeEndObject();
    }
}

一个简单的测试

public static void main(String[] args) throws JsonProcessingException {
    User user = new User(1L, "Mike");
    ObjectMapper om = new ObjectMapper();
    om.writeValueAsString(user);
    System.out.println(om.writeValueAsString(user));
}

输出将是

{"inputFields":[{"name":"id","value":1},{"name":"firstName","value":"Mike"}]}

【讨论】:

  • 你用的是什么版本的jackson?
  • 在示例中我使用了 jackson 2.6.1
  • field.setAccessible(true); 添加到循环中,我将接受这个答案作为最“正确”和优雅的答案。
  • true,为了防止使用反射的可访问性,应该设置该标志。谢谢
【解决方案2】:

创建一个InputFields 类并将User 对象数据移动到其中,然后再转换为json。

编辑:InputFields 类显然与所需的 json 结果具有相同的结构。

【讨论】:

  • 并使该字段成为 InputFields 类中的集合。或者创建一个自定义转换器。
  • @stepanian 其实 inputFields 不是什么大问题,问题是名称-值对的结构
  • 我明白这一点。 InputFields 类将具有该结构。
【解决方案3】:

只是 stepanian 回答的一个例子,但我更喜欢 dumitru 的方式来实现 CustomSerializer。

  1. 创建一个 InputField 类

    public class InputField {
    
        private String name;
        private String value;
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
    }
    
  2. 解析用户

    public static List<InputField> parseInputFields(Object model) {
        List<InputField> inputFields = new ArrayList<InputField>();
    
        Field[] field = model.getClass().getDeclaredFields();
        try {
            for (int j = 0; j < field.length; j++) {
    
                InputField inputField = new InputField();
    
                inputField.setName(field[j].getName());
                inputField.setValue(String.valueOf(field[j].get(model));
    
                inputFields.add(inputField);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    
        return inputFields;
    } 
    
  3. 测试

    public static void main(String[] args) throws JsonProcessingException {
        User user = new User(1L, "Mike");
    
        Map<String, Object> tmpMap=new HashedMap();
        tmpMap.put("inputFields", parseInputFields(user));
    
        ObjectMapper om = new ObjectMapper();
        System.out.println(om.writeValueAsString(tmpMap));
    }
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-25
    • 2011-10-17
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多