Git Product home page Git Product logo

jb4jsonld's People

Contributors

ledsoft avatar psiotwo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

jb4jsonld's Issues

General handling of temporal data

As a follow up to #9, handling of date, time and datetime objects should be solved in general.
First, support for Java 8 Date/Time API should be added.
Second, serialization of these (and java.util.Date) should perhaps be configurable (time in milliseconds vs. formatted string).
Third, deserialization should be working accordingly as well.

jsonld2java should support blank nodes

jsonld2java transformation generates exception if input jsonld document has a blank node. The exception is due to failed attempt to transform blank node to an URI (i assume it from the stack trace that i saw). Although i did not try it on this data, in text below i created 2 examples of semantically same jsonld document. First one should succeed in transformation while second one i believe would not ...

First, jsonld document that i think would work:

{
  "http://example.org/property" : "value",
  "http://example.org/property2" : {
  	"http://example.org/inner-property" : "otherValue"
   }
}

If i transform previous jsonld document using jsonld transformation "flattened", i will get equivalent jsonld document which i believe would fail within jsonld2java transformation:

{
  "@graph": [
    {
      "@id": "_:b0",
      "http://example.org/property": "value",
      "http://example.org/property2": {
        "@id": "_:b1"
      }
    },
    {
      "@id": "_:b1",
      "http://example.org/inner-property": "otherValue"
    }
  ]
}

Workaround in this case would be removing all "@id" properties, since all of the objects are referenced only once. This is however not general case..

Link to the example in jsonld playground.

MultilingualString values without language tag are not supported

Currently, MultilingualString values without language (represented by a null language tag value) are serialized as

{
  "null": "Language-less value"
}

This is not correct w.r.t. the JSON-LD 1.1 specification and while jsonld-java, which we are using for processing JSON-LD, works under JSON-LD 1.0, this causes issues with integration with client-side libraries like jsonld.js.
The aforementioned input should be serialized as:

{
  "@none": "Language-less value"
}

handle polymorfism in property ranges during deserialization

I have a class C with a single-valued property p and a range constraint which restrict the range of p to a class D (this constraint is espressed as a subclass constraint assertion on C). D has two subclasses D' and D''. In my json file I has a property assertion
stating that an individual of class C is linked to an individual which belongs to both classes D' and D'' (D'' is the same) via the property p. I would expect that the individual of class D' would be deserialized as individual of (the java class corresponding to) D, in light of the constraint on C. However an AmbiguousTargetTypeException is thrown as D' and D'' are detected as possible target candidates. See cz.cvut.kbss.jsonld.deserialization.util.TargetClassResolver, row 48.

Please let me know if a pull request to fix it as I would expect may be appropriate.

Implement deferred reference resolution

JSON-LD allows using references to objects via their id. The problem is, when the input is being processed, the order of attributes might change and thus the id reference could be deserialized before the full object.

A solution to this problem could be to defer resolution of such references until the full object has been encountered.

Duplicate @type property

When an entity has a types field, the serialization creates duplicate @type property, one for the @OWLClass value and the other for the value of @Types attribute.

These should be unified.

Allow property overriding

As a user, I want to be able to override property mapping. The main use case after implementing #16 would be preventing term mapping conflicts in context, e.g., when two classes have a field with the same name but different mapped property, it is not possible to serialize them at the same time because a term mapping conflict would occur in the context. Property overriding would solve this.

Note that this has to work both for serialization and deserialization.

Handling Language Indexing

It would be great to be able to translate jsonld language map fields defined with Language Indexing.

I'm not sure what the best way to handle this would be with regards to the Java mappings though.

Unable to serialize individuals in unmapped properties

I created a Class annotated with the OWLClass annotation. This class has a field properties annotated with the @Properties JOPA annotation. Following javadoc, my properties field has tipe Map<String, Set<Object>>. Infact, I need to specify an object unmapped property here. Thus, for analogy with @OWLObjectProperty, I put in this map a singleton with an object of type URI. I would expect that, when serializing, this URI is used to construct the property target as an individual with this URI as @Id. However, instead the property is interpreted as a datatype property and the URI as a string literal.

I tried also with using an object of another class annotated as @OWLClass instead of a URI. In this case the string literal produced in serialization is the class name. I suppose that in both cases just the toString method of the object is used to generate the literal.

With debugging, I saw that fields annotated with @Property annotation are processed by the cmethod cz.cvut.kbss.jsonld.serialization.PropertyFieldSerializer.serializePropertyValues which I assume works only for literals.

java2jsonld serialization handles references to node objects incorrectly

If java object model contains more than one reference to the same java object it is serialized into json-ld incorrectly:

  • first reference of the java object is serialized into the json-ld object node, where content of whole java object is serialized e.g.:{
{
    "http://onto.fel.cvut.cz/ontologies/documentation/has_related_question" : {
      "@id": "http://onto.fel.cvut.cz/1-q",
      "@type": "http://onto.fel.cvut.cz/ontologies/documentation/question"
    }
}
  • any subsequent reference to the java object is serialized using "string" property (!!! this is incorrect !!!) e.g. :
{
   "http://onto.fel.cvut.cz/ontologies/documentation/has_related_question" : "http://onto.fel.cvut.cz/1-q"
}

From such document it is inferred by a json-ld processor, that subsequent references refers to string "http://onto.fel.cvut.cz/1-q", not IRI http://onto.fel.cvut.cz/1-q.

To fix this issue there are 2 possible solutions:

  1. jsonld can be extended with a context that defines relevant properties values of type "@id", thus we could fix the example by adding:
{
  "@context": {
    "http://onto.fel.cvut.cz/ontologies/documentation/has_related_question" : { 
       "@id" : "http://onto.fel.cvut.cz/ontologies/documentation/has_related_question", 
       "@type" : "@id"        
    }
  },    
  "@graph": [
    {
.....
  1. references must be explicitly defined as references to object nodes, i.e. w.r.t. the example it would be:
{
 "http://onto.fel.cvut.cz/ontologies/documentation/has_related_question": [
      {
        "@id": "http://onto.fel.cvut.cz/871-q"
      }
  ....

Ability to assume target type if not provided in jsonld.

Currently in ActivityStreams4J, when a target type parameter is missing from the jsonld, an exception ocurs:

{
  "@context" : "https://www.w3.org/ns/activitystreams",
  "name" : "Foo",
  "id" : "http://example.org/foo"
}
cz.cvut.kbss.jsonld.exception.TargetTypeException: Neither class social.pantheon.activitystreams4j.core.ObjectDTO nor any of its subclasses matches the types [].

	at cz.cvut.kbss.jsonld.deserialization.util.TargetClassResolver.getTargetClass(TargetClassResolver.java:53)
	at cz.cvut.kbss.jsonld.deserialization.expanded.Deserializer.resolveTargetClass(Deserializer.java:45)

It would be great if there was a way to specify that JB4JSONLD was allowed to assume the type of the object to be the base class it was told to serialize if no type parameter was provided.

Relaxing check about single cardinality constraints in json deserialization DefaultInstanceBuilder)

Le C be an OWL class which defines an single value cardinality constraint (cardinality==1) on some property p.
Now let i be an individual of class C, which occurs two times in a json file so that in both the occurrences the property p is present, with values respectively o and o'. When the DefaultInstanceBuilder encounter the second occurrence of i during the parsing of the json file, it throws a JsonDeserializationException ๐Ÿ‘Ž

Encountered multiple values of property

However, if o and o' are equals the single value constraint is not actually violated. In such a cases I think that avoiding to throw the exception would make the api more robust against strang but correct json files.

Support serialization with context

As a user, I want to be able to serialize the Java objects into JSON-LD with @context attribute. This way, even applications without support for JSON-LD could understand the output.

Polymorphism support

JB4JSON-LD should be able to deserialize an object when an abstract return type is specified.

This would mean that the most specific concrete implementation matching the object's types whould be found and the JSON-LD would be deserialized as it.

For instance, consider the classes:

@OWLClass(iri = "A")
interface A {}

@OWLClass(iri = "B")
class B implements A {}

Then calling

A result = deserializer.deserialize(data, A.class);

on JSON-LD looking like this:

{
  "@type": ["A", "B"]
}

Should result in result being of type B.

Support embedded contexts

As a user, I sometimes use the same attribute name for mapping different properties in the object model. This is problematic for serialization as it currently leads to an AmbiguousTermMappingException. Instead, JSON-LD allows to use embedded contexts that locally override mapping of terms.
JB4JSON-LD should support this. An alternative is implementation of #41 .

Deserialization into @Properties field does not support objects

When a JSON-LD object references another object via a unmapped property, the deserializer is not able to put this reference value into the @Properties field value.

This is related to Enhancement #5 , as the reference will have to be deserialized so that only its IRI is put into the properties map.

Serialization with embedded context attempts to add the context to incorrect node

When serializing a graph where an embedded context is generated for an instance (let's call it A) which has a reference to a collection of further objects, JB4JSON-LD attempts to add the embedded context to the collection node, causing the following exception:

java.lang.UnsupportedOperationException: Prepending items is not supported by this composite node.

	at cz.cvut.kbss.jsonld.serialization.model.CompositeNode.prependItem(CompositeNode.java:45)
	at cz.cvut.kbss.jsonld.serialization.JsonLdTreeBuilder.closeObject(JsonLdTreeBuilder.java:86)
	at cz.cvut.kbss.jsonld.serialization.JsonLdTreeBuilder.closeCollection(JsonLdTreeBuilder.java:129)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.closeCollection(ObjectGraphTraverser.java:221)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverseCollection(ObjectGraphTraverser.java:78)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverse(ObjectGraphTraverser.java:64)
	at cz.cvut.kbss.jsonld.serialization.serializer.compact.ObjectPropertyValueSerializer.serialize(ObjectPropertyValueSerializer.java:40)
	at cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingObjectPropertyValueSerializer.serialize(ContextBuildingObjectPropertyValueSerializer.java:19)
	at cz.cvut.kbss.jsonld.serialization.JsonLdTreeBuilder.visitAttribute(JsonLdTreeBuilder.java:110)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.visitAttribute(ObjectGraphTraverser.java:213)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.serializeFields(ObjectGraphTraverser.java:116)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverseSingular(ObjectGraphTraverser.java:94)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverse(ObjectGraphTraverser.java:66)
	at cz.cvut.kbss.jsonld.serialization.serializer.compact.ObjectPropertyValueSerializer.serialize(ObjectPropertyValueSerializer.java:40)
	at cz.cvut.kbss.jsonld.serialization.serializer.context.ContextBuildingObjectPropertyValueSerializer.serialize(ContextBuildingObjectPropertyValueSerializer.java:19)
	at cz.cvut.kbss.jsonld.serialization.JsonLdTreeBuilder.visitAttribute(JsonLdTreeBuilder.java:110)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.visitAttribute(ObjectGraphTraverser.java:213)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.serializeFields(ObjectGraphTraverser.java:116)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverseSingular(ObjectGraphTraverser.java:94)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverse(ObjectGraphTraverser.java:66)
	at cz.cvut.kbss.jsonld.serialization.traversal.ObjectGraphTraverser.traverse(ObjectGraphTraverser.java:57)
	at cz.cvut.kbss.jsonld.serialization.ContextBuildingJsonLdSerializer.buildJsonTree(ContextBuildingJsonLdSerializer.java:82)
	at cz.cvut.kbss.jsonld.serialization.JsonLdSerializer.serialize(JsonLdSerializer.java:79)

NoClassDefFoundError: cz/cvut/kbss/jopa/model/MultilingualString on version 0.8.2

Using cz.cvut.kbss.jsonld.jackson.JsonLdModule.JsonLdModule to configure the jackson object mapper in a spring boot application i got the following error

java.lang.NoClassDefFoundError: cz/cvut/kbss/jopa/model/MultilingualString
cz.cvut.kbss.jsonld.deserialization.DefaultInstanceBuilder.openCollection(DefaultInstanceBuilder.java:156)
cz.cvut.kbss.jsonld.deserialization.expanded.CollectionDeserializer.processValue(CollectionDeserializer.java:48)
cz.cvut.kbss.jsonld.deserialization.expanded.ObjectDeserializer.processValue(ObjectDeserializer.java:57)
cz.cvut.kbss.jsonld.deserialization.expanded.ExpandedJsonLdDeserializer.deserialize(ExpandedJsonLdDeserializer.java:51)
cz.cvut.kbss.jsonld.jackson.deserialization.JacksonJsonLdDeserializer.deserialize(JacksonJsonLdDeserializer.java:62)
com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:195)
com.fasterxml.jackson.databind.deser.std.ObjectArrayDeserializer.deserialize(ObjectArrayDeserializer.java:21)
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3267)
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239)
org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227)
org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:104)
org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:998)
org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:981)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:714)
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:602)

I just included

  <dependency>
  	<groupId>cz.cvut.kbss.jsonld</groupId>
  	<artifactId>jb4jsonld-jackson</artifactId>
  	<version>0.8.2</version>
  </dependency>

May be i need to import some other jopa module?

Handling of java.util.Date

Instances of java.util.Date should be serialized as the number of milliseconds since epoch and it should be possible to read them back into java.util.Date objects again.

Deserialize object as plain identifier object property value

It would be nice to be able to deserialize full blown objects as values of identifier-base object property. For example

{
  "@id": "http://krizik.felk.cvut.cz/ontologies/jb4jsonld#UNSC",
  "@type": "http://krizik.felk.cvut.cz/ontologies/jb4jsonld/Organization",
  "brands": [
    "Spartan-II",
    "Mjolnir IV"
  ],
  "http://purl.org/dc/terms/created": "Mon Aug 01 10:43:04 CEST 2016",
  "http://www.w3.org/2000/01/rdf-schema#label": "UNSC"
}

Deserialize as value of:

...
@OWLObjectProperty(iri = "http://krizik.felk.cvut.cz/ontologies/jb4jsonld/isMemberOf")
private URI employer;   // Would be http://krizik.felk.cvut.cz/ontologies/jb4jsonld#UNSC
...

This would simulate the application working with a smaller model than that available in the JSON-LD data.

Support enums

As a user, I want to be able to serialize/deserialize enum values to/from JSON-LD.

Support JOPA namespaces

JOPA allows to declare namespaces (using @Namespace annotation) to shorted IRIs when mapping classes and attributes. JB4JSON-LD needs to be able to resolve the namespaces and output full IRIs into the JSON-LD.

Disjoint polymorphic object parameter ranges

I'm not sure if a github issue is the best place to discuss this, so feel free to close this if you feel it's the wrong place for this discussion, but...

How would you recommend handling a property such as https://www.w3.org/TR/activitystreams-vocabulary/#dfn-url where the Range can be either an xsd:anyURI or a Link object, or https://www.w3.org/TR/activitystreams-vocabulary/#dfn-attachment where the Range can be either Object or Link.

Many of the properties in ActivityStreams4J are defined as java.lang.Object for this reason, but this obviously reduces the amount of type information avaliable and therefore causes UnknownPropertyException.

Any suggestions would be greatly appreciated.

issues when deserializing subclasses

I defined a ParentClass and two subclasses ChildClassA and ChildClassB. ParentClass has a single field, annotated with @id, whereas the child classes has no additional fields.


	@OWLClass(iri = "http://www.example.org/parent")
	public static class ParentClass {
		@Id
		private String id;

		public ParentClass() {
			this.id = "http://noid.org";
		}

		public String getId() {
			return id;
		}

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

	}

	@OWLClass(iri = "http://www.example.org/childa")
	public static class ChildClassA extends ParentClass {
	}

	@OWLClass(iri = "http://www.example.org/childb")
	public static class ChildClassB extends ParentClass {
	}

AssertionError on attempt to pass invalid JSON-LD

An assertion fails when JsonLdProcessor.expand returns an empty list in JacksonJsonLdDeserializer::deserialize if the input is not expandable or valid jsonld.

java.lang.AssertionError
	at cz.cvut.kbss.jsonld.deserialization.expanded.ExpandedJsonLdDeserializer.deserialize(ExpandedJsonLdDeserializer.java:42)
	at cz.cvut.kbss.jsonld.jackson.deserialization.JacksonJsonLdDeserializer.deserialize(JacksonJsonLdDeserializer.java:63)
	at cz.cvut.kbss.jsonld.jackson.deserialization.JacksonJsonLdDeserializer.deserializeWithType(JacksonJsonLdDeserializer.java:102)

An exception would likely be better in this case to allow for logical error handling in downstream applications.

Support for custom serializers/deserializers

As a user, I sometimes find the default (de)serialization behavior of JB4JSON-LD unsuitable for my requirements. I want to be able to override the default behavior using my own (de)serializer. This overriding should be possible on class and field level.

Similar feature is available in Jackson via the @JsonSerialize and @JsonDeserialize annotations.

Support external contexts

As a user, I want to be able to reference external contexts in a JSON-LD document serialization. This could reduce the size of the serialization output significantly and allow centralized management of term mapping.

Ignoring attributes

As a user, I want to be able to mark entity attributes as "ignored". Such attributes should be skipped in serialization. Consider whether such attributes should be ignored on deserialization as well.

Support serializing individuals as string with context info

As a developer, I want to be able to make JSON-LD output as close to plain JSON as possible. This should include the ability to serialize individuals (plain identifier object property values as well as enum constants mapped to individuals) as string with info about the value being in identifier in the context.

For example, currently, an individual is serialized as an object with id:

{
  "@context": {
    "attribute": "http://example.org/attribute"
  },
  "attribute": {
    "@id": "http://www.w3.org/2002/07/owl#ObjectProperty"
  } 
}

Instead, it should be possible to configure the serialization (with context) so that the output is as follows:

{
  "@context": {
    "attribute": {
      "@id": "http://example.org/attribute",
      "@type": "@id"
    }
  },
  "attribute": "http://www.w3.org/2002/07/owl#ObjectProperty"
}

This should make it easier for clients to digest the JSON-LD. Note that this will not have any influence on deserialization and serialization without context.

Support for plain identifier object properties

Similar to JOPA, an entity can have an object property value which is not another entity, but just an identifier (IRI) of another individual, which is not mapped by the object model. JB4JSON-LD should handle this.

E.g.

...
@OWLObjectProperty(iri = "http://onto.fel.cvut.cz/ontologies/form/has-answer-origin")
private URI origin;
...

deserializing subclass defined in external maven artifact

I have the following hierarchy of @OWLClasses

  • a parent class with just @id
@OWLClass(iri = "http://www.example.org/parent")
public class ParentClass implements Serializable {
	@Id
	protected String id;

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

	public String getId() {
		return id;
	}
}
  • and two empty child classes
@OWLClass(iri = "http://www.example.org/childa")
public class ChildClassA extends ParentClass implements Serializable {

}
@OWLClass(iri = "http://www.example.org/childb")
public class ChildClassB extends ParentClass implements Serializable {

}

When deserializing an object of class ChildClassA but using a reader for ParentClass, the deserializer correctly return on object of class ChildClassA. Here follows the test

	@Test
	public void shouldDeserializationReturnMostSpecificSubclass() throws JsonProcessingException {
		final ChildClassA a = new ChildClassA();
		a.setId("http://example.com/childa/a");
		final String serialized = "{\"@id\":\"http://example.com/childa/a\",\"@type\":[\"http://www.example.org/childa\",\"http://www.example.org/parent\",\"http://www.example.org/grandparent\"]}";
		final ObjectReader r = jsonLdObjectMapper().readerFor(ParentClass.class);
		final ParentClass deserialized = r.readValue(serialized);
		assertEquals(a.getId(), deserialized.getId());
		assertTrue(deserialized instanceof ChildClassA);
	}

The project is compiled with maven and tests is run by the maven surefire plugin. However, I decided to pack the class hiararchy above in a standalone maven artifact, and import the same artifact in another maven project by declaring it as dependency. The same test above, moved in this project which does not contains the hierarchy sources but just include it as dependency, fails because the deserializer returns an object of class ParentClass

java2jsonld serialization is too verbose for java properties without values

Java objects with empty properties (i.e. empty collections or null values for simple java fields) are serialized to jsonld by empty array [] and empty objects {}. This is unnecessary and makes jsonld file hard to read in case where there are many empty properties.

An example of an annotated class and respective jsonld file is in attachment. The redundant part of jsonld is:
"form:has-preceding-question": [],
"form:has-question-origin": {}

It would be sufficient to exclude serialization of properties form:has-preceding-question, form:has-question-origin from the final output.

serialized-excerpt.jsonld.txt
Question.java.txt

AssertionErrors from valid JSON-LD input

A number of valid activitystreams/jsonld tests in ActivityStreams4J error with AssertionErrors from JB4JSONLD in a variety of places:

  • cz.cvut.kbss.jsonld.deserialization.expanded.Deserializer.getObjectTypes(Deserializer.java:54)
  • cz.cvut.kbss.jsonld.deserialization.DefaultInstanceBuilder.openObjectForProperty(DefaultInstanceBuilder.java:71)
  • cz.cvut.kbss.jsonld.deserialization.expanded.ExpandedJsonLdDeserializer.deserialize(ExpandedJsonLdDeserializer.java:42)

I can provide specific examples of inputs if necessary, but it might be easier for you to clone ActivityStreams4J and run the tests yourself to be able to debug them, or look at the assertion errors from a recent build (please ignore the tests that fail with errors other than java.lang.AssertionError).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.