How can I unmarshal a message that was marshalled using a QName local part different then what is expected?
My example is below:
Given an object to unmarshal that has been created using a marshal method such as
marshaller.marshal( new JAXBElement(
new QName("urn:somenamespace","DifferentNameMessage"),
OriginalMessageType.class,
originalMsg),
result);
(As I understand this code snippet, the QName is indicating to make the root element use a substitue name tag other than what is specified
in the original schema. Essentially using a substitute name method. For instance, in the QName above the original
tag would have been "NameMessage" but the message was marshalled using local part "DifferentNameMessage".)
I would normally use a method of unmarshalling such as:
String xmlString = convertStreamToString(in);
final StringReader xmlReader = new StringReader(xmlString);
final StreamSource xmlSource = new StreamSource(xmlReader);
JAXBContext jaxbContext = JAXBContext.newInstance(OriginalMessageType.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
JAXBElement ret = null;
ret = unmarshaller.unmarshal(xmlSource, OriginalMessageType.class);
But, if I use this method then the JAXBElement ret name is for the QName that was use to marshalled it, yet the DeclaredType is for
OriginalMessageType.class and the unmarshalled message contains null element values for the expected sub-elements, even though
the original message contains valid values for these sub-elements.
i am wondering if it is possible to specifiy the substitute QName during unmarshalling to indicate that it is a substitute and then to use the original tag in its place?
The following is correct:
ret = unmarshaller.unmarshal(xmlSource, OriginalMessageType.class);
Is this how you made your JAXBContext when your marshalled?
JAXBContext jaxbContext = JAXBContext.newInstance(OriginalMessageType.class);
Things to try:
Did you verify the marshalled document is correct?
What happens when you use the same JAXBContext for both marshal and unmarshal?
Related
Suppose I have an InputStream that contains JSON data, and I want to convert it to a Map(Key Value Pairs), so for example I can write that to a log file.
What is the easiest way to take the InputStream and convert it to a Map?
public String convertInputStreamToMap(InputStream isobj) {
// ???
}
I've tried converting to String which works as expected but when the data is really long the data will be incomplete. So I want some easiest way to directly convert this to Map.
Use ObjectMapper from com.fasterxml.jackson.databind to directly convert inputstream to Map:
for example:
objectMapper.readValue(is, Map.class);
there is a built-in class in groovy to parse json: groovy.json.JsonSlurper
it has parse method that accepts almost any source including InputStream
def url = 'https://httpbin.org/get'.toURL()
def json = url.withInputStream{inputStream->
new groovy.json.JsonSlurper().parse(inputStream)
}
println json.headers
and if you want to convert InputStream to String, groovy provides additional methods to work with InputStream class: https://docs.groovy-lang.org/latest/html/groovy-jdk/java/io/InputStream.html
the following code reads the content of this InputStream using specified charset and returns it as a String.
String s = inputStream.getText("UTF-8")
Can someone please explain to me how writer.toString would hold the customer data? It appears as though marshal(customer,writer) somehow modified the writer. Please see below, thanks:
Customer customer = new Customer();
customer.setId(42);
customer.setName("Bill Burke");
JAXBContext ctx = JAXBContext.newInstance(Customer.class);
StringWriter writer = new StringWriter();
ctx.createMarshaller().marshal(customer, writer);
[See here:]
String custString = writer.toString(); // how did writer suddenly take on value?
customer = (Customer)ctx.createUnmarshaller()
.unmarshal(new StringReader(custString));
StringWriter is a Writer-implementation that writes into a StringBuffer. When you call write(), you append to that StringBuffer. ToString() calls toString() on that StringBuffer and returns it.
Marshaller.marshal() just serializes the JAXB objects into XML, and writes them into the Writer (and thus into the StringBuffer). The StringReader in your second snippet then reads from the String created by StringBuffer.
I'm guessing that the reason writer is able to write the content is because the marshaller must have called a method inside the write object which changed whatever write points to. Therefore, after the marshal(), the writer references new data.
http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html (see bottom)
I currently have this:
JAXBContext jaxbContext = JAXBContext.newInstance(javaObject.getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
StringWriter stringWriter = new StringWriter();
jaxbMarshaller.marshal(javaObject, stringWriter);
String xml = stringWriter.toString();
The object contains a list of data_objects. As long as that list of data_objects is under 17 items I get a complete xml response. Once I have more than that the xml gets truncated. It does not throw an error. The xml string just has '...' at the end
<DataDetailObject xmlns:xsi="...
If I use System.Out instead of stringWriter I see the entire xml transformation correctly. What am I missing? Should I be using a different output for the marshalling?
The ... may be the behaviour of the debugger or viewer that you are using to introspect the String. If you write it to System.out you should see everything working correctly.
I get the following error while trying to evaluate a predicate in a a4solution:
Fatal error in /some/path at line 9 column 2: Field "field
(A/Attribute <: type)" is not bound to a legal value during
translation.
Here is the code at the origin of the error:
for(ExprVar a : solution.getAllAtoms()){
// additional checks are here to assure that a is of an "appropriate type"
solution.eval(predicate.call(a));
}
In my vain attempts to solve this problem by myself, I read from this source http://code.google.com/p/alloy4eclipse/issues/detail?id=86 that the way the solution has been read from the file might cause this problem.
But the source doesn't give further details.
I have created my solution object as follows :
XMLNode xml = new XMLNode(new StringReader(source.getFileContent()));
this.solution = A4SolutionReader.read(new ArrayList<Sig>(), xml);
Thank you for your support
The problem was that the expression to be evaluated (predicate.call(a)) was drawn from one CompModule object (namely the predicate function was taken from there) while the solution object, against which the expression was evaluated, was not obtained from the same CompModule, but was read from a file.
Generally, when reading a solution from an xml file, to be on the safe side, it is recommended to reread and reconstruct everything from that xml file, e.g.,
XMLNode xmlNode = new XMLNode(new File("my_solution.xml"));
String alloySourceFilename = xmlNode.iterator().next().getAttribute("filename");
Module module = CompUtil.parseEverything_fromFile(rep, null, alloySourceFilename);
A4Solution ans = A4SolutionReader.read(module.getAllReachableSigs(), xmlNode);
In some cases it suffices to just pass the sigs from the original CompModule to the reconstructed solution:
XMLNode xmlNode = new XMLNode(new File("my_solution.xml"));
A4Solution ans = A4SolutionReader.read(originalModule.getAllReachableSigs(), xmlNode);
Why after De-Serialization the object reference not same as it was before serilization.
ok let me Explain this
I am Having a String
string test = "TestString";
Now I do Serilization
DataContractJsonSerializer _DataContractJsonSerializer
= new DataContractJsonSerializer(typeof(string));
MemoryStream ms = new MemoryStream();
_DataContractJsonSerializer.WriteObject(ms, test);
var jsonString = Encoding.Default.GetString(ms.ToArray());
Now I do DeSerilization from jsonstring into actual value
MemoryStream ms1 =
new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(string));
string DeseriliaedStrring = serializer.ReadObject(ms1) as string;
here in DeseriliaedStrring i got the actual value but if i check there reference they are not equal
bool isReferenceEqual = object.ReferenceEquals(DeseriliaedStrring, test);
Serialization creates copies of the object's values. Deserialization creates a completely new instance with the copied values.
Edit in response to your comment below: Deserialization doesn't call a constructor. If this is a problem, then override with ISerializable. This will serialise based on a call to ISerializable.GetObjectData and then call a particular constructor with SerializationInfo and StreamingContext fields.
When you serialize and deserialize an object, the deserialization will create an instance base on the serialized data. This is of course not the same instance as the original one, that seems fairly logical. After all, you have the following process:
You have an object instance
You create a string instance that is a representation of that object instance
You create an object instance based on the serialized data in the string
If you take into consideration that the original instance might have mutated, that the deserialization can happen in another process, even in another machine, it becomes quite clear that deserialization could not possibly return the original instance.
In this particular case, when the object is a String, you could imagine that the string interning would make the system reuse the old instance (if the deserialization happened within the same AppDomain). But that would probably* require DataContractJsonSerializer to be aware of this, which would make it unnecessarily complex.
*) I am actually not quite sure of exactly what part of the system that takes care of string interning.