Hi :slightly_smiling_face: I am writing a POM solv...
# serialization
l
Hi 🙂 I am writing a POM solver and I need to deserialize POM files. I am using xmlutil but I am stuck with the pom properties. I need to deserialize both cases:
Copy code
<properties>
  <a.propery>1</a.property>
  <property>
    <name>another.property</name>
    <value>2</value>
  </property>
</properties>
I was going for (tho it has mainly written by ChatGPT4 based on here):
Copy code
@Serializable
@XmlSerialName(
    value = "project",
    namespace = POM_XML_NAMESPACE,
)
data class ProjectModel(
  // ...
  val properties: Properties? = null,
  // ...
)
@Serializable(with = PropertiesSerializer::class)
@XmlSerialName(
    value = "properties",
    namespace = POM_XML_NAMESPACE,
)
data class Properties(
    val properties: Map<String, String> = emptyMap()
)
object PropertiesSerializer : KSerializer<Properties> {
    override val descriptor: SerialDescriptor = MapSerializer(String.serializer(), String.serializer()).descriptor
    override fun deserialize(decoder: Decoder): Properties {
        decoder as? XML.XmlInput
            ?: throw SerializationException("${this::class.simpleName} can be used only by XML")
        val reader = decoder.input as? XmlBufferedReader
            ?: throw SerializationException("${this::class.simpleName} can be used only by XmlBufferedReader")
        val properties = mutableMapOf<String, String>()
        while (reader.hasNext() && reader.eventType != EventType.END_ELEMENT) {
            if (reader.eventType == EventType.START_ELEMENT) {
                val localName = reader.localName
                if (localName == "property") {
                    var name: String? = null
                    var value: String? = null
                    while (reader.hasNext() && !(reader.eventType == EventType.END_ELEMENT && reader.localName == "property")) {
                        if (reader.eventType == EventType.START_ELEMENT) {
                            when (reader.localName) {
                                "name" -> name = reader.consecutiveTextContent()
                                "value" -> value = reader.consecutiveTextContent()
                            }
                        }
                        reader.nextTag()
                    }
                    name ?: throw SerializationException("Property name is not specified")
                    value ?: throw SerializationException("Property value is not specified")
                    properties[name] = value
                } else {
                    properties[localName] = reader.consecutiveTextContent()
                }
            }
            reader.nextTag()
        }
        return Properties(properties)
    }
    override fun serialize(encoder: Encoder, value: Properties) {
        val output = encoder as? XML.XmlOutput
            ?: throw SerializationException("This class can be saved only by XML")
        val writer = output.target
        writer.startTag(POM_XML_NAMESPACE, "properties", "")
        value.properties.forEach { (k, v) ->
            writer.startTag(POM_XML_NAMESPACE, k, "")
            writer.text(v)
            writer.endTag(POM_XML_NAMESPACE, k, "")
        }
        writer.endTag(POM_XML_NAMESPACE, "properties", "")
    }
}
But no luck. It says that it cannot find a match for the tag
<properties>
and errors with:
Copy code
nl.adaptivity.xmlutil.serialization.UnknownXmlFieldException: Could not find a field for name (org.jetbrains.packagesearch.maven.ProjectModel) {<http://maven.apache.org/POM/4.0.0>}project/{<http://maven.apache.org/POM/4.0.0>}properties (Element)
  candidates: {<http://maven.apache.org/POM/4.0.0>}modelVersion (Element), {<http://maven.apache.org/POM/4.0.0>}groupId (Element), {<http://maven.apache.org/POM/4.0.0>}artifactId (Element), {<http://maven.apache.org/POM/4.0.0>}version (Element), {<http://maven.apache.org/POM/4.0.0>}name (Element), {<http://maven.apache.org/POM/4.0.0>}description (Element), {<http://maven.apache.org/POM/4.0.0>}url (Element), {<http://maven.apache.org/POM/4.0.0>}organization (Element), {<http://maven.apache.org/POM/4.0.0>}parent (Element), {<http://maven.apache.org/POM/4.0.0>}packaging (Element), {<http://maven.apache.org/POM/4.0.0>}value (Element), {<http://maven.apache.org/POM/4.0.0>}dependencies (Element), {<http://maven.apache.org/POM/4.0.0>}dependencyManagement (Element), {<http://maven.apache.org/POM/4.0.0>}licenses (Element), {<http://maven.apache.org/POM/4.0.0>}developers (Element), {<http://maven.apache.org/POM/4.0.0>}scm (Element), {<http://maven.apache.org/POM/4.0.0>}issueManagement (Element) at position Line number = 47
Column number = 15
System Id = null
Public Id = null
Location Uri= null
CharacterOffset = 1907
where line 47 is
<properties>
. Do you have any clue?
h
Do you need MPP support? If not, I would recommend the official maven pom library because it also supports parent poms and you get the same behavior as maven.
l
We are using such solution, but it is very clunky. The resolution algorithm is pretty simple, i just need to get the model first