0

Я абстрактный класс называется Message:Deserialize от ObjectInputStream к одному из подклассов

public abstract class Message 
{ 
    public enum MsgType 
    { 
     TypeA, TypeB 
    } 

    public String Sender; 
    public MsgType Type; 
} 

который имеет два подкласса:

public class MessageA extends Message 
{ 
    public String A; 

    public MessageA() 
    { 
     Type = MsgType.TypeA; 
    } 
} 

public class MessageB extends Message 
{ 
    public int B; 

    public MessageB() 
    { 
     Type = MsgType.TypeB; 
    } 
} 

Я десериализация объектов непосредственно из ObjectsInputStream использования Simple библиотеки по либо MessageA, либо MessageB в зависимости от того, какой из них считывается из потока.

Я попытался сделать это:

inputStream = new ObjectInputStream(clientSocket.getInputStream()); 
Message msg = serializer.read(Message.class, inputStream); 
// check whether it's MessageA or MessageB by checking Type 

Но это не работает, потому что компилятор не может десериализации MessageA или MessageB к Message класса. Кроме того, я уверен, что я потеряю поля подкласса в этом процессе.

Есть ли подходящий способ для этого?

+0

ссылка указывает на библиотеку для ведения XML сериализации и десериализации, который написан и читать с помощью текстовых файлов. Но вы используете ObjectInputStream для чтения данных, что полезно для чтения двоичных данных. Пожалуйста, объясни. – laune

+0

Эта библиотека имеет методы Serializer.validate() в различных формах. Если я это правильно понимаю, вы можете использовать этот метод, чтобы увидеть, представляет ли XML MessageA или MessageB. Когда вы знаете, вы можете вызвать чтение с помощью соответствующего параметра класса. – laune

+0

Я должен десериализовать объекты в C# тоже. Я не думаю, что это возможно с помощью собственного механизма сериализации Java. –

ответ

1
public class Main { 
    public static void main(String[] args) throws Exception { 
     Serializer serializer = new Persister(); 
     MessageB messageB = new MessageB("example", 123); 
     File result = new File("example.xml"); 
     serializer.write(messageB, result); 
     MessageB msgB = serializer.read(MessageB.class, result); 
     System.out.println(msgB); 
     try { 
      if(serializer.validate(MessageA.class, result)){ 
       System.out.println("valid for MessageA"); 
      } 
     } catch(Exception e){ 
      System.out.println("NOT valid for MessageA"); 
     } 
     try { 
      if(serializer.validate(MessageB.class, result)){ 
       System.out.println("valid for MessageB"); 
      } 
     } catch(Exception e){ 
      System.out.println("NOT valid for MessageB"); 
     } 
    } 
} 

public abstract class Message{ 
    public enum MsgType { 
     TypeA, TypeB 
    } 
    @Element 
    private String sender; 
    @Element 
    private MsgType type; 
    protected Message(){ 
    } 
    protected Message(String s, MsgType t){ 
     sender = s; 
     type = t; 
    } 
    public String getSender(){ return sender; } 
    public MsgType getType(){ return type; } 
    public String toString(){ 
     return "type=" + type + ", sender=" + sender; 
    } 
} 

@Root 
public class MessageA extends Message { 
    @Element 
    private String a; 
    public MessageA(){ 
    } 
    public MessageA(String s, String a){ 
     super(s, MsgType.TypeA); 
     this.a = a; 
    } 
    public String getA(){ return a; } 
    public String toString(){ 
     return super.toString() + ", a=" + a; 
    } 
} 
@Root 
public class MessageB extends Message { 
    @Element 
    private int b; 
    public MessageB(){ 
    } 
    public MessageB(String s, int b){ 
     super(s, MsgType.TypeA); 
     this.b = b; 
    } 
    public int getB(){ return b; } 
    public String toString(){ 
     return super.toString() + ", b=" + b; 
    } 
} 

Это работает очень хорошо.

type=TypeA, sender=example, b=123 
NOT valid for MessageA 
valid for MessageB 

Файл XML записывается в виде:

<messageB> 
    <sender>example</sender> 
    <type>TypeA</type> 
    <b>123</b> 
</messageB> 
+0

Спасибо за помощь. Я полагался исключительно на 'validate()' возвращаемое значение, которое должно было быть «истинным, если документ соответствует схеме XML класса», но проверка того, выбрано ли исключение, действительно работает *. –

+0

Да, эта смесь исключений + возвращаемое значение не является «лучшей практикой». – laune

+0

Я тоже так думал, но поскольку это не серьезный проект, я доволен этим решением. –

0

Добавить @root (имя = "...") аннотацию к каждому из подклассов

Например:

public interface StringOperation { 
    String performOperation(String input); 
} 

@Root(name = "upperCaseStringOperation") 
public class UpperCaseStringOperation implements StringOperation { 
    public UpperCaseStringOperation() { 
    } 

    @Override 
    public String performOperation(String input) { 
     return (input == null) ? (null) : (input.toUpperCase()); 
    } 
} 

@Root(name = "lowerCaseStringOperation") 
public class LowerCaseStringOperation implements StringOperation { 
    public LowerCaseStringOperation() { 
    } 

    @Override 
    public String performOperation(String input) { 
     return (input == null) ? (null) : (input.toLowerCase()); 
    } 
} 

@Root(name = "noOpStringOperation") 
public class NoOpStringOperation implements StringOperation { 
    public NoOpStringOperation() { 
    } 

    @Override 
    public String performOperation(String input) { 
     return input; 
    } 
} 

@Root 
public class Data { 

    @Element 
    private String name; 

    @Element 
    private StringOperation nameOperation; 

    @Element 
    private String email; 

    @Element 
    private StringOperation emailOperation; 

    public Data() { 
     nameOperation = new NoOpStringOperation(); 
     emailOperation = new NoOpStringOperation(); 
    } 

    public String getName() { 
     return name; 
    } 

    public String getProcessedName() { 
     return nameOperation.performOperation(getName()); 
    } 

    public String getEmail() { 
     return email; 
    } 

    public String getProcessedEmail() { 
     return emailOperation.performOperation(getEmail()); 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public void setEmail(String email) { 
     this.email = email; 
    } 

    public void setNameOperation(StringOperation operation) { 
     this.nameOperation = operation; 
    } 

    public void setEmailOperation(StringOperation operation) { 
     this.emailOperation = operation; 
    } 

    @Override 
    public String toString() { 
     return String.format("Data(name = %s, processedName = %s, email = %s, processedEmail = %s)", 
          getName(), 
          getProcessedName(), 
          getEmail(), 
          getProcessedEmail()); 
    } 
} 

Код:

 Data before = new Data(); 
     before.setName("Joseph Wallflower"); 
     before.setNameOperation(new UpperCaseStringOperation()); 
     before.setEmail("[email protected]"); 
     before.setEmailOperation(new LowerCaseStringOperation()); 

     System.out.format("BEFORE: %s%n", before.toString()); 

     Serializer serializer = new Persister(); 
     File file = new File(System.getenv("USERPROFILE")+File.separator+"Documents"+File.separator+"simple.xml"); 
     serializer.write(before, file); 

Результаты в:

<data> 
    <name>Joseph Wallflower</name> 
    <nameOperation class="simplexml.UpperCaseStringOperation"/> 
    <email>[email protected]</email> 
    <emailOperation class="simplexml.LowerCaseStringOperation"/> 
</data> 
Смежные вопросы