【问题标题】:How to serialize / deserialize a Option<> class (functional java) with JSON?如何使用 JSON 序列化/反序列化 Option<> 类(函数式 java)?
【发布时间】:2014-04-09 07:18:56
【问题描述】:

我在 java 中使用 Class Option 来替代使用具有更好类型检查的 null。 http://functionaljava.googlecode.com/svn/artifacts/2.20/javadoc/fj/data/Option.html

我的问题是如何在 JSON 中序列化/反序列化我的以下代码?

public Option<? extends ClassA> a;

使用 ObjectMapper 序列化的结果总是:

"a" : [ "Option$Some", {
  "none" : false,
  "some" : true
} ]

反序列化不起作用。

感谢您的回复。

p/s:我粘贴我的完整代码如下:

public class TestOption {

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "@class")
@JsonSubTypes({
        @JsonSubTypes.Type(value = SoundDog.class, name = "soundDog"),
        @JsonSubTypes.Type(value = SoundCat.class, name = "soundCat"), })
public static abstract class Sound {
    abstract String getSound();
}

public static class SoundDog extends Sound {

    @Override
    String getSound() {
        return "gau gau";
    }

}

public static class SoundCat extends Sound {

    @Override
    String getSound() {
        return "meo meo";
    }

}


@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({ @JsonSubTypes.Type(value = Dog.class, name = "dog"),
        @JsonSubTypes.Type(value = Cat.class, name = "cat"), })
public static abstract class Animal {
    public Animal() {
    }

    public Animal(String name) {
        this.name = name;
    }

    public String name;
    public Animal parent;
    public Option<? extends Sound> sound;
}

@JsonTypeName("dog")
public static class Dog extends Animal {
    public Dog() {
    }

    public Dog(String name) {
        super(name);
    }
}

@JsonTypeName("cat")
public static class Cat extends Animal {
    public Cat() {
    }

    public Cat(String name) {
        super(name);
    }
}

public static void main(String... args) throws Exception {
    TestOption zoo = createZoo();

    ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

    String json1 = mapper.writerWithDefaultPrettyPrinter()
            .writeValueAsString(zoo);
    System.out.println("+++>>>" + json1);

    zoo = mapper.readValue(json1, TestOption.class);

    for(Animal animal : zoo.animals){
        System.out.println("Animal name = " + animal.name);
        if(animal.sound != null){
            System.out.println("Animal sound = " + animal.sound.some().getSound()); 
        }           

    }

    String json2 = mapper.writerWithDefaultPrettyPrinter()
            .writeValueAsString(zoo);

    System.out.println("Equals: " + json1.equals(json2));
}

private static TestOption createZoo() {
    TestOption zoo = new TestOption();

    Dog dog1 = new Dog("Dog1");
    dog1.sound = Option.some(new SoundDog());
    Dog dog2 = new Dog("Dog2");
    dog2.sound = Option.some(new SoundDog());
    Cat cat1 = new Cat("Cat1");
    cat1.sound = Option.some(new SoundCat());
    Cat cat2 = new Cat("Cat2");

    dog2.parent = dog1;
    cat2.parent = cat1;

    zoo.add(dog1);
    zoo.add(dog2);
    zoo.add(cat1);
    zoo.add(cat2);

    return zoo;
}

public void add(Animal animal) {
    animals.add(animal);
}

public void setAnimals(List<Animal> list) {
    this.animals = list;
}

public List<Animal> getAnimals() {
    return this.animals;
}

public List<Animal> animals = new ArrayList<Animal>();
}

更新:

我的解决方案是这样的:

import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

import eu.cea.ladis.tools.serializableFJ.Option;

public class TestClass {

public static class MyJsonSerializer extends JsonSerializer<MyObject> {

    @Override
    public void serialize(MyObject value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {
        jgen.writeStartObject();

        Option<String> myString = value.getMyString();

        if(myString.isNone()){
            jgen.writeStringField("myString", "null");  
        }

        if(myString.isSome()){
            jgen.writeStringField("myString", myString.some()); 
        }


        jgen.writeEndObject();
    }

}

public static class MyJsonDeserializer extends JsonDeserializer<MyObject> {

    @Override
    public MyObject deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        ObjectCodec oc = jp.getCodec();
        JsonNode node = oc.readTree(jp);
        return new MyObject(node.get("myString").asText());
    }

}

@JsonSerialize(using = MyJsonSerializer.class)
@JsonDeserialize(using = MyJsonDeserializer.class)
public static class MyObject {
    public Option<String> myString;

    public MyObject() {
        super();
        myString = Option.some("test string");
    }

    public MyObject(String myString) {
        super();
        if(myString != null){
            this.myString = Option.some(myString);
        }else{
            this.myString = Option.none();
        }
    }

    public Option<String> getMyString() {

        return myString;

    }
}

public static void main(String[] args) throws IOException {
    MyObject obj = new MyObject();
    ObjectMapper objectMapper = new ObjectMapper();     

    String json1 = objectMapper.writeValueAsString(obj);
    System.out.println("json1>>"+json1);

    MyObject obj2 = objectMapper.readValue(json1, MyObject.class);

    String json2 = objectMapper.writeValueAsString(obj2);

    System.out.println("json2>>"+json2);

    System.out.println("Equals: " + json1.equals(json2));

}

 } 

【问题讨论】:

  • 您使用的是哪种 JSON 库?如果你使用 Jackson marshaller,你可以使用自己的序列化器/反序列化器,然后实现自己的序列化/反序列化代码
  • 我使用 Jackson ObjectMapper 来序列化/反序列化。你能举一个使用 Jackson marshaller 的例子(或链接)吗?谢谢 Angelo Immediata。
  • 您可能需要自己的JsonDeserializer。或者,查看 mixins。
  • 感谢 Sotririos 的回复

标签: java json serialization


【解决方案1】:

您应该使用 JsonSerializer 和 JsonDeserializer 这是文档的链接:http://fasterxml.github.io/jackson-databind/javadoc/2.3.0/ 如果你想使用它,一个非常基本的示例是这样的(它只是一个示例......尝试在你自己的代码中进行竞争):

public class MyJsonDeserializer extends JsonDeserializer<MyObject>
{
 //Deserializer implementation
}

@JsonDeserialize(using=MyJsonDeserializer.class)
public class MyObject
{
  //MyObj properties and methos
}

我希望这会有所帮助 安杰洛

【讨论】:

  • 谢谢安吉洛。我在上面粘贴了我的完整代码。我的哪个班级需要使用 JsonSerializer 和 JsonDeserializer ?
  • @V-Q-ANGUYEN 通过查看您的代码,我猜您可以将 JsonSerializer 和 JsonDeserializer 添加到 Animal 抽象类中(如果我没记错的话,您在 Animal 类中使用的 Option 类有问题; 所以所有子类都可以使用自定义的反序列化器/序列化器
  • 谢谢@Angelo。我尝试了一些方法,但它不起作用。如果没有,我发现同样的问题如下stackoverflow.com/questions/10723826/…
  • 终于,我明白了。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-13
  • 2020-07-07
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-09
相关资源
最近更新 更多